<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss1full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"> 

  <channel rdf:about="http://justatheory.com">
    <title>Just a Theory</title>
    <link>http://justatheory.com</link>
    <description>Theory waxes practical. By David E. Wheeler.</description>
    <language>en-us</language>
    <dc:creator>David E. Wheeler (david@justatheory.com)</dc:creator>
    <dc:rights>Copyright David E. Wheeler</dc:rights>
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <admin:generatorAgent rdf:resource="http://www.raelity.org/apps/blosxom/?v=2.1" />
    <admin:errorReportsTo rdf:resource="mailto:david@justatheory.com" />

    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-oracle.html" />
        <rdf:li rdf:resource="http://justatheory.com/culture/rationality-and-faith.html" />
        <rdf:li rdf:resource="http://justatheory.com/travel/france/2013/more-sun.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-sqlite.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-on-windows.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-homebrew-tap.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/postgresql/bootstrap-bucardo-mulitmaster.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/programming/perl/modules/localetextdomain-msg-compile.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-trust-but-verify.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-rebase.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/postgresql/format.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/changing-sqitch_ids.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/postgresql/mock-serialization-failures.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/programming/perl/modules/dist-zilla-localetextdomain.html" />
        <rdf:li rdf:resource="http://justatheory.com/computers/databases/sqitch-symbolism.html" />

      </rdf:Seq>
    </items>


    <image rdf:resource="http://meerkat.oreillynet.com/icons/meerkat-powered.jpg" />

  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rdf+xml" href="http://feeds.feedburner.com/justatheory/rssfull" /><feedburner:info uri="justatheory/rssfull" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /></channel>

  <image rdf:about="http://justatheory.com/logo.gif">
    <title>Just a Theory</title>
    <url>http://justatheory.com/logo.gif</url>
    <link>http://justatheory.com</link>
  </image>

  <item rdf:about="http://justatheory.com/computers/databases/sqitch-oracle.html">
    <title>Sqitch on Oracle</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/tewgv9XNcUM/sqitch-oracle.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-05-09T22:11-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>Sqitch is available from the usual locations. For Oracle support, you&rsquo;ll need the <a href="http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html">Instant Client</a>, including SQL*Plus. Make sure you have <a href="http://www.orafaq.com/wiki/ORACLE_HOME"><code>$ORACLE_HOM</code></a> set and you&rsquo;ll be ready to install. Via CPAN, it&rsquo;s</p>

<pre><code>cpan install App::Sqitch DBD::Oracle
</code></pre>

<p>Via <a href="http://brew.sh">Homebrew</a>:</p>

<pre><code>brew tap theory/sqitch
brew install sqitch-oracle
</code></pre>

<p>Via ActiveState PPM, install <a href="http://www.activestate.com/activeperl/downloads">ActivePerl</a>, then run:</p>

<pre><code>ppm install App-Sqitch DBD-Oracle
</code></pre>

<a class="left" href="http://www.pgcon.org/2013/"><img src="http://www.pgcon.org/2013/images/pgcon-220x250.png" alt="PGCon 2013" /></a>

<p>There are a few other minor tweaks and fixed in this release; check the <a href="https://metacpan.org/source/DWHEELER/App-Sqitch-0.970/Changes">release notes</a> for details.</p>

<p>Want more? I will be giving a half-day tutorial, entitled &ldquo;<a href="http://www.pgcon.org/2013/schedule/events/615.en.html">Agile Database Development</a>,&rdquo; on database development with <a href="http://git-scm.com/">Git</a>, <a href="http://sqitch.org/">Sqitch</a>, and <a href="http://pgtap.org/">pgTAP</a> at on May 22 <a href="http://www.pgcon.org/2013/">PGCon 2013</a> in Ottawa, Ontario. Come on up!</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/tewgv9XNcUM" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-oracle.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/culture/rationality-and-faith.html">
    <title>Rationality and Faith</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/CmDHKo5jd2E/rationality-and-faith.html</link>
    <description />
    <dc:subject>/culture</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-04-24T16:43-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>I got an invitation to write on <a href="https://medium.com/">Medium</a> a couple weeks ago. I have been pondering some more philosophical posts lately, so I thought I&rsquo;d try posting there. My first post, “<a href="https://medium.com/on-culture/11cfd5b919f6">Misguided Delusion</a>,” tries to pull apart the the false dichotomy between faith and rationality. Yeah, really. That kind of thinking is a throwback to a <a href="/autobiographical/five_things.html">previous career path</a>, but one that has, of course, always stuck with me. And I am very happy with how the post turned out.</p>

<p>It remains to be seen whether or not I write more stuff like that. It&rsquo;s rewarding, but time-consuming.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/CmDHKo5jd2E" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/culture/rationality-and-faith.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/travel/france/2013/more-sun.html">
    <title>More Sun</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/Clwv9EFzOsA/more-sun.html</link>
    <description />
    <dc:subject>/travel/france/2013</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-04-17T06:01-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<div class="box" style="float:none"><a href="http://www.flickr.com/photos/decar66/8583754790/" title="Arles from the Arena"><img style="float:none" src="http://farm9.staticflickr.com/8102/8583754790_3297ccf5f7_c.jpg" alt="Arles from the Arena" /></a>
<p class="caption" style="text-align:left !important">Arles from the Arena by <a href="http://www.flickr.com/photos/decar66/">Salva Barbera</a> (<a href="http://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a>)</p>
</div>

<p>We spent seven weeks last summer <a href="http://www.justatheory.com/travel/france/2012/a-rouen.html">in Northern France</a>. Man it was an awesome time. None of us wanted to leave! Well, almost true. The thing about Normandy is that the weather is very much like Portland—except that <a href="http://www.urbandictionary.com/define.php?term=Juneuary">Juneuary</a> lasts through July and August. We were so desperate for sun that we spent a week <a href="http://www.flickr.com/photos/theory/sets/72157630781097042/">in Barcelona</a>.</p>

<p>This summer will be different. Much warmer. No, not Portland, but two months in <a href="https://en.wikipedia.org/wiki/Arles">Arles</a>, in <a href="https://en.wikipedia.org/wiki/Provence">Provence</a>. Yes, we are once again doing a home exchange, this time in the city in which <a href="https://en.wikipedia.org/wiki/Vincent_van_Gogh">Vincent Van Gogh</a> famously spent his <a href="https://en.wikipedia.org/wiki/Vincent_van_Gogh#Artistic_breakthrough_and_final_years">final years</a>. Nice, warm, Mediterranean weather.</p>

<p>We can&rsquo;t wait.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/Clwv9EFzOsA" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/travel/france/2013/more-sun.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-sqlite.html">
    <title>Sqitch: Now with SQLite Support</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/7MhhHR5RIOk/sqitch-sqlite.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-04-10T00:27-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>This week I released <a href="https://metacpan.org/release/DWHEELER/App-Sqitch-0.961/">Sqitch v0.961</a>. There are a number of great new features v0.95x, including the beginning of two features I&rsquo;ve had in mind since the beginning: VCS integration and support for multiple databases.</p>

<p>First the VCS integration. This comes in the form of the new <a href="https://metacpan.org/module/sqitch-checkout"><code>checkout</code> command</a>, which automatically makes database changes for you when you change VCS branches. Say you have two branches, &ldquo;widgets&rdquo; and &ldquo;big-fix&rdquo;, and that their Sqitch plans diverge. If you&rsquo;re in the &ldquo;widgets&rdquo; branch and want to switch to &ldquo;big-fix&rdquo;, just run</p>

<pre><code>sqitch checkout big-fix
</code></pre>

<p>Sqitch will look at the &ldquo;big-fix&rdquo; plan, figure out the last change in common with &ldquo;widgets&rdquo;, and revert to it. Then it checks out &ldquo;big-fix&rdquo; and deploys. That&rsquo;s it. Yes, you could do this yourself, but do you really remember the last common change between the two branches? Do you want to take the time to look for it, then revert, check out the new branch, and deploy? This is exactly the sort of common developer task that Sqitch aims to take the pain out of, and I&rsquo;m thrilled to provide it.</p>

<p>You know what&rsquo;s awesome, though? <em>This feature never occurred to me.</em> I didn&rsquo;t come up with it, and didn&rsquo;t implement it. No, it was dreamt up and submitted in a pull request by <a href="https://github.com/rdunklau/">Ronan Dunklau</a>. I have wanted VCS integration since the beginning, but had yet to get &lsquo;round to it. Now Ronan has jumpstarted it. A million thanks!</p>

<p>One downside: it&rsquo;s currently Git-only. I plan to add infrastructure for <a href="https://github.com/theory/sqitch/issues/25">supporting multiple VCSes</a>, probably with Git and Subversion support to begin with. Watch for that in v0.970 in the next couple months.</p>

<p>The other big change is the addition of <a href="http://sqlite.org/">SQLite</a> support alongside the existing <a href="http://postgresql.org/">PostgreSQL</a> support. Fortunately, I was able to re-use nearly all the code, so the SQLite adapter is just <a href="https://github.com/theory/sqitch/blob/master/lib/App/Sqitch/Engine/sqlite.pm">a couple hundred lines long</a>. For the most part, Sqitch on SQLite works just like on PostgreSQL. The main difference is that Sqitch stores its metadata in a separate SQLite database file. This allows one to use a single metadata file to maintain multiple databases, which can be important if you use multiple databases as schemas pulled into a single connection via <a href="http://www.sqlite.org/lang_attach.html"><code>ATTACH DATABASE</code></a>.</p>

<p>Curious to try it out? Install Sqitch <a href="https://metacpan.org/release/App-Sqitch">from CPAN</a> or <a href="https://github.com/theory/homebrew-sqitch">via the Homebrew Tap</a> and then follow the new <a href="https://metacpan.org/module/sqitchtutorial-sqlite">Sqitch SQLite tutorial</a>.</p>

<p>Of the multitude of other <a href="https://metacpan.org/source/DWHEELER/App-Sqitch-0.961/Changes">Changes</a>, one other bears mentioning: the new <a href="https://metacpan.org/module/sqitch-plan"><code>plan</code> command</a>. This command is just like <a href="https://metacpan.org/module/sqitch-log"><code>log</code></a>, except that it shows what is in the plan file, rather than what changes have been made to the database. This can be useful for quickly listing what&rsquo;s in a plan, for example when you need to remember the names of changes required by a change you&rsquo;re about to <a href="https://metacpan.org/module/sqitch-add"><code>add</code></a>. The <code>--oneline</code> option is especially useful for this functionality. An example from <a href="https://metacpan.org/module/sqitchtutorial">the tutorial</a>&rsquo;s plan:</p>

<pre><code>&gt; sqitch plan --oneline
In sqitch.plan
6238d8 deploy change_pass
d82139 deploy insert_user
7e6e8b deploy pgcrypto
87952d deploy delete_flip @v1.0.0-dev2
b0a951 deploy insert_flip
834e6a deploy flips
d0acfa deploy delete_list
77fd99 deploy insert_list
1a4b9a deploy lists
0acf77 deploy change_pass @v1.0.0-dev1
ec2dca deploy insert_user
bbb98e deploy users
ae1263 deploy appschema
</code></pre>

<p>I personally will be using this a lot, Yep, scratching my own itch here. What itch do you have to scratch with Sqitch?</p>

<p>In related news, I&rsquo;ll be giving a tutorial at <a href="http://pgcon.org/2013/">PGCon</a> next month, entitled &ldquo;<a href="http://www.pgcon.org/2013/schedule/events/615.en.html">Agile Database Development</a>&rdquo;. We&rsquo;ll be developing a database for a web application using <a href="http://git-scm.com/">Git</a> for source code management, <a href="http://sqitch.org/">Sqitch</a> for database change management, and <a href="http://pgtap.org/">pgTAP</a> for unit testing. This is the stuff I do all day long at work, so you can also think of it as &ldquo;Theory&rsquo;s Pragmatic approach to Database Development.&rdquo; See you there?</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/7MhhHR5RIOk" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-sqlite.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-on-windows.html">
    <title>Sqitch on Windows (and Linux, Solaris, and OS X)</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/v_1wjJlrHfA/sqitch-on-windows.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-02-27T00:35-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>Thanks to the hard-working hamsters at the <a href="http://code.activestate.com/ppm/">ActiveState PPM Index</a>, Sqitch is available for installation on Windows. According to the <a href="http://code.activestate.com/ppm/App-Sqitch/">Sqitch PPM Build Status</a>, the latest version is now available for installation. All you have to do is:</p>

<ol>
<li>Download and install <a href="http://www.activestate.com/activeperl/downloads#">ActivePerl</a></li>
<li>Open the Command Prompt</li>
<li>Type <code>ppm install App-Sqitch</code></li>
</ol>


<p>As of this writing, only PostgreSQL is supported, so you will need to <a href="http://www.postgresql.org/download/windows/">install PostgreSQL</a>.</p>

<p>But otherwise, that&rsquo;s it. In fact, this incantation works for any OS that ActivePerl supports. Here&rsquo;s where you can find the <code>sqitch</code> executable on each:</p>

<ul>
<li>Windows: <code>C:\perl\site\bin\sqitch.bat</code></li>
<li>Mac OS X: <code>~/Library/ActivePerl-5.16/site/bin/sqitch</code> (Or <code>/usr/local/ActivePerl-5.16/site/bin</code> if you run <code>sudo ppm</code>)</li>
<li>Linux: <code>/opt/ActivePerl-5.16/site/bin/sqitch</code></li>
<li>Solaris/SPARC (<a href="http://www.activestate.com/compare-editions">Business edition</a>-only): <code>/opt/ActivePerl-5.16/site/bin/sqitch</code></li>
</ul>


<p>This makes it easy to get started with Sqitch on any of those platforms without having to become a Perl expert. So go for it, and then get started with <a href="https://github.com/theory/sqitch/blob/master/lib/sqitchtutorial.pod">the tutorial</a>!</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/v_1wjJlrHfA" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-on-windows.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-homebrew-tap.html">
    <title>Sqitch Homebrew Tap</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/QbRKzlS5wGc/sqitch-homebrew-tap.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-02-22T07:09-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>If <a href="http://sqitch.org/" title="Sqitch: Sane database schema change management">Sqitch</a> is to succeed, it needs to get into the hands of as many people as possible. That means making it easy to install for people who are not Perl hackers and don&rsquo;t want to deal with CPAN. The <a href="https://github.com/theory/homebrew-sqitch">Sqitch Homebrew Tap</a> is my first public stab at that. It provides a series of &ldquo;Formulas&rdquo; for <a href="http://mxcl.github.com/homebrew/">Homebrew</a> users to easily download, build, and install Sqitch and all of its dependencies.</p>

<p>If you are one of these lucky people, here&rsquo;s how to configure the Sqitch tap:</p>

<pre><code>brew tap theory/sqitch
</code></pre>

<p>Now you can install the core Sqitch application:</p>

<pre><code>brew install sqitch
</code></pre>

<p>That&rsquo;s it. Make sure it works:</p>

<pre><code>&gt; sqitch --version
sqitch (App::Sqitch) 0.953
</code></pre>

<p>It won&rsquo;t do you much good without support for your database, though.
Currently, there is a build for PostgreSQL. Note that this requires the
Homebrew core PostgreSQL server:</p>

<pre><code>brew install sqitch_pg
</code></pre>

<p>Sqitch hasn&rsquo;t been ported to other database engines yet, but once it is, expect other formulas to follow. But if you use PostgreSQL (or just want to experiment with it), you&rsquo;re ready to rock! I suggest following along <a href="https://github.com/theory/sqitch/blob/master/lib/sqitchtutorial.pod">the tutorial</a> or taking in <a href="https://speakerdeck.com/theory/sane-database-change-management-with-sqitch">the latest iteration of the introductory presentation</a> (video of an older version <a href="http://vimeo.com/50104469">here</a>).</p>

<p>My thanks to IRC user &ldquo;mistym&rdquo; for the help and suggestions in getting this going. My Ruby is pretty much rusted through, soI could not have done it without the incredibly responsive help!</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/QbRKzlS5wGc" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-homebrew-tap.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/postgresql/bootstrap-bucardo-mulitmaster.html">
    <title>Bootstrapping Bucardo Master/Master Replication</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/UNm1Wdh2iXw/bootstrap-bucardo-mulitmaster.html</link>
    <description />
    <dc:subject>/computers/databases/postgresql</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-02-12T22:11-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>Let&rsquo;s say you have a production database up and running and you want to set up a second database with <a href="http://bucardo.org/">Bucardo</a>-powered replication between them. Getting a new master up and running without downtime for an existing master, and without losing any data, is a bit fiddly and under-documented. Having just figured out one way to do it with the forthcoming Bucardo 5 code base, I wanted to blog it as much for my own reference as for yours.</p>

<p>First, let&rsquo;s set up some environment variables to simplify things a bit. I&rsquo;m assuming that the database names and usernames are the same, and only the host names are different:</p>

<pre><code>export PGDATABASE=widgets
export PGHOST=here.example.com
export PGHOST2=there.example.com
export PGSUPERUSER=postgres
</code></pre>

<p>And here are some environment variables we&rsquo;ll use for Bucardo configuration stuff:</p>

<pre><code>export BUCARDOUSER=bucardo
export BUCARDOPASS=*****
export HERE=here
export THERE=there
</code></pre>

<p>First, let&rsquo;s create the new database as a schema-only copy of the existing database:</p>

<pre><code>createdb -U $PGSUPERUSER -h $PGHOST2 $PGDATABASE
pg_dump -U $PGSUPERUSER -h $PGHOST --schema-only $PGDATABASE \
| psql -U $PGSUPERUSER -h $PGHOST2 -d $PGDATABASE
</code></pre>

<p>You might also have to copy over roles; use <code>pg_dumpall --globals-only</code> to do that.</p>

<p>Next, we configure Bucardo. Start by telling it about the databases:</p>

<pre><code>bucardo add db $HERE$PGDATABASE dbname=$PGDATABASE host=$PGHOST user=$BUCARDOUSER pass=$BUCARDOPASS
bucardo add db $THERE$PGDATABASE dbname=$PGDATABASE host=$PGHOST2 user=$BUCARDOUSER pass=$BUCARDOPASS
</code></pre>

<p>Tell it about all the tables we want to replicate:</p>

<pre><code>bucardo add table public.foo public.bar relgroup=myrels db=$HERE$PGDATABASE 
</code></pre>

<p>Create a multi-master database group for the two databases:</p>

<pre><code>bucardo add dbgroup mydbs $HERE$PGDATABASE:source $THERE$PGDATABASE:source  
</code></pre>

<p>And create the sync:</p>

<pre><code>bucardo add sync mysync relgroup=myrels dbs=mydbs autokick=0
</code></pre>

<p>Note <code>autokick=0</code>. This ensures that, while deltas are logged, they will not be copied anywhere until we tell Bucardo to do so.</p>

<p>And now that we know that any changes from here on in will be queued for replication, we can go ahead and copy over the data. The only caveat is that we need to disable the Bucardo triggers on the target system, so that our copying does not try to queue up. We do that by setting the <a href="http://www.postgresql.org/docs/9.2/static/runtime-config-client.html#GUC-SESSION-REPLICATION-ROLE"><code>session_replication_role</code> GUC</a> to &ldquo;replica&rdquo; while doing the copy:</p>

<pre><code>pg_dump -U $PGSUPERUSER -h $PGHOST --data-only -N bucardo $PGDATABASE \
| PGOPTIONS='-c session_replication_role=replica' \
psql -U $PGSUPERUSER -h $PGHOST2 -d $PGDATABASE
</code></pre>

<p>Great, now all the data is copied over, we can have Bucardo copy any changes that have been made in the interim, as well as any going forward:</p>

<pre><code>bucardo update sync mysync autokick=1
bucardo reload config
</code></pre>

<p>Bucardo will fire up the necessary syncs and copy over any interim deltas. And any changes you make to either system in the future will be copied to the other.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/UNm1Wdh2iXw" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/postgresql/bootstrap-bucardo-mulitmaster.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/programming/perl/modules/localetextdomain-msg-compile.html">
    <title>Dist::Zilla::LocaleTextDomain for Translators</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/0L1CtIY5aC8/localetextdomain-msg-compile.html</link>
    <description />
    <dc:subject>/computers/programming/perl/modules</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-01-08T23:36-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>Here&rsquo;s a followup on my post about <a href="/computers/programming/perl/modules/dist-zilla-localetextdomain.html">localizing Perl modules with Locale::TextDomain</a>. <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a> was great for developers, less so for translators. A <a href="http://sqitch.org/" title="Sqitch: Sane database change management">Sqitch</a> translator asked how to test the translation file he was working on. My only reply was to compile the whole module, then install it and test it. Ugh.</p>

<p>Today, I released <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain v0.85</a> with a new command, <a href="https://metacpan.org/module/Dist::Zilla::App::Command::msg_compile"><code>msg-compile</code></a>. This command allows translators to easily compile just the file they&rsquo;re working on and nothing else. For pure Perl modules in particular, it&rsquo;s pretty easy to test then. By default, the compiled catalog goes into <code>./LocaleData</code>, where convincing the module to find it is simple. For example, I updated the <a href="https://github.com/theory/sqitch/blob/master/t/sqitch">test <code>sqitch</code> app</a> to take advantage of this. Now, to test, say, the French translation file, all the translator has to do is:</p>

<pre><code>&gt; dzil msg-compile po/fr.po
[LocaleTextDomain] po/fr.po: 155 translated messages, 24 fuzzy translations, 16 untranslated messages.

&gt; LANGUAGE=fr ./t/sqitch foo
"foo" n'est pas une commande valide
</code></pre>

<p>I hope this simplifies things for translators. See the <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain#But-Im-a-Translator">notes for translators</a> for a few more words on the subject.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/0L1CtIY5aC8" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/programming/perl/modules/localetextdomain-msg-compile.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-trust-but-verify.html">
    <title>Sqitch: Trust, But Verify</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/Vbb4vs0R4XY/sqitch-trust-but-verify.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2013-01-04T00:57-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>New today: <a href="https://metacpan.org/release/DWHEELER/App-Sqitch-0.950/">Sqitch v0.950</a>. There are a few bug fixes, but the most interesting new feature in this release is the <a href="https://metacpan.org/module/App::Sqitch::Command::verify"><code>verify</code> command</a>, as well as the complementary <code>--verify</code> option to the <a href="https://metacpan.org/module/App::Sqitch::Command::deploy"><code>deploy</code> command</a>. The <a href="https://metacpan.org/module/App::Sqitch::Command::add"><code>add</code> command</a> has created <code>test</code> scripts since the beginning; they were renamed <code>verify</code> in v0.940. In v0.950 these scripts are actually made useful.</p>

<p>The idea is simply to test that a deploy script did what it was supposed to do. Such a test should make no assumptions about data or state other than that affected by the deploy script, so that it can be run against a production database without doing any damage. If it finds that the deploy script failed, it should die.</p>

<p>This is easier than you might at first think. Got a Sqitch change that creates a table with two columns? Just <code>SELECT</code> from it:</p>

<pre><code>SELECT user_id, name
  FROM user
 WHERE FALSE;
</code></pre>

<p>If the table does not exist, the query will die. Got a change that creates a function? Make sure it was created by checking a privilege:</p>

<pre><code>SELECT has_function_privilege('insert_user(text, text)', 'execute');
</code></pre>

<p>PostgreSQL will throw an error if the function does not exist. Not running PostgreSQL? Well, you&rsquo;re probably not using Sqitch <a href="https://github.com/theory/sqitch/issues?labels=engine&amp;state=open">yet</a>, but if you were, you might force an error by dividing by zero. Here&rsquo;s an example verifying that a schema exists:</p>

<pre><code>SELECT 1/COUNT(*)
  FROM information_schema.schemata
 WHERE schema_name = 'myapp';
</code></pre>

<p>At this point, Sqitch doesn&rsquo;t care at all what you put into your verify scripts. You just need to make sure that they indicate failure by throwing an error when passed to the database command-line client.</p>

<p>The best time to run a change verify script is right after deploying the change. The <code>--verify</code> option to the <a href="https://metacpan.org/module/App::Sqitch::Command::deploy"><code>deploy</code> command</a> does just that. If a verify script fails, the deploy is considered to have failed. Here&rsquo;s what failure looks like:</p>

<pre><code>&gt; sqitch deploy
Deploying changes to flipr_test
  + appschema ................. ok
  + users ..................... ok
  + insert_user ............... ok
  + change_pass @v1.0.0-dev1 .. ok
  + lists ..................... psql:verify/lists.sql:7: ERROR:  column "timestamp" does not exist
LINE 1: SELECT nickname, name, description, timestamp
                                            ^
Verify script "verify/lists.sql" failed.
not ok
Reverting all changes
  - change_pass @v1.0.0-dev1 .. ok
  - insert_user ............... ok
  - users ..................... ok
  - appschema ................. ok
Deploy failed
</code></pre>

<p>Good, right? In addition, you can always verify the state of a database using the <a href="https://metacpan.org/module/App::Sqitch::Command::verify"><code>verify</code> command</a>. It runs the verify scripts for all deployed changes. It also ensures that all the deployed changes were deployed in the same order as they&rsquo;re listed in the plan, and that no changes are missing. The output is similar to that for <code>deploy</code>:</p>

<pre><code>&gt; sqitch verify
Verifying flipr_test
  * appschema ................. ok
  * users ..................... ok
  * insert_user ............... ok
  * change_pass @v1.0.0-dev1 .. ok
  * lists ..................... ok
  * insert_list ............... ok
  * delete_list ............... ok
  * flips ..................... ok
  * insert_flip ............... ok
  * delete_flip @v1.0.0-dev2 .. ok
  * pgcrypto .................. ok
  * insert_user ............... ok
  * change_pass ............... ok
Verify successful
</code></pre>

<p>Don&rsquo;t want verification tests/scripts? Use <code>--no-verify</code> when you call <a href="https://metacpan.org/module/App::Sqitch::Command::add"><code>sqitch add</code></a> and none will be created. Or tell it never to create verify scripts by setting the turning off the <code>add.with_verify</code> option:</p>

<pre><code>sqitch config --bool add.with_verify no
</code></pre>

<p>If you somehow run <code>deploy --verify</code> or <code>verify</code> anyway, Sqitch will emit a warning for any changes without verify scripts, but won&rsquo;t consider them failures.</p>

<h3>Up Front Dependency Checking</h3>

<p>The other significant change in v0.950 is that the <code>deploy</code> and <code>revert</code> commands (and, by extension the <a href="https://metacpan.org/module/App::Sqitch::Command::deploy"><code>rebase</code> command</a>) now verify that dependencies have been checked before deploying or reverting anything. Previously, Sqitch checked the dependencies for each change before deploying it, but it makes much more sense to check them for all changes to be deployed before doing anything at all. This reduces the chances of unexpected reversions.</p>

<p>Still hacking on Sqitch, of course, though nearly all the commands I initially envisioned are done. <a href="https://github.com/theory/sqitch/issues?milestone=3">Next up</a>, I plan to finally implement support for <a href="http://sqlite.org/">SQLite</a>, add a few more commands to simplify plan file modification, and to create a new site, since <a href="http://sqlite.org/">the current site</a> is woefully out-of-date. Until then, though, check out <a href="http://www.slideshare.net/justatheory/sane-sql-change-management-with-sqitch">this presentation</a> and, of course, <a href="https://metacpan.org/module/sqitchtutorial">the tutorial</a>.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/Vbb4vs0R4XY" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-trust-but-verify.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-rebase.html">
    <title>Sqitch Update: All Your Rebase Are…Never Mind</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/k8lSB6Kw37s/sqitch-rebase.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-12-04T07:27-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>I&rsquo;ve been doing a lot of Sqitch-based database development at <a href="http://iovation.com/">work</a>. Overall it has worked quite well. Except for one thing: often the order in which changes would be arranged would change from one run to the next. Oy.</p>

<h3>Out of Order</h3>

<p>The reason? The plan parser would perform a <a href="https://en.wikipedia.org/wiki/Topological_sorting" title="Wikipedia: “Topological sorting”">topological sort</a> of all the changes between tags based on their dependencies. I&rsquo;ve been careful, for the most part, to keep my changes in the proper order in our plan files, but the topological sort would often pick a different order. Still valid in terms of dependency ordering, but different from the plan file.</p>

<p>Given the same inputs, the sort always produced the same order. However, whenever I added a new changes (and I do that all the time while developing), there would then be a new input, which could result in a completely different order. The downside is that I would add a change, run <code>sqitch deploy</code>, and it would die because it thought something needed to be deployed that had already been deployed, simply because it sorted it to come after an undeployed change. <em>So annoying.</em>. It also caused problems in for production deployments, because different machines with different Perls would sort the plans in different ways.</p>

<p>So I re-wrote the sorting part of the the plan parser so that it no longer sorts. The list of changes is now always identical to the order in the plan file. It still checks dependencies, of course, only now it throws an exception if it finds an ordering problem, rather than re-ordering for you. I&rsquo;ve made an effort to tell the user how to move things around in the plan file to fix ordering issues, so hopefully everything will be less mysterious.</p>

<p>Of course, many will never use dependencies, in which case this change has effect. But it was important to me, as I like to specify dependencies as much as I can, for my own sanity.</p>

<p>See? There&rsquo;s that theme!</p>

<h3>Everyone has a Mom</h3>

<p>Speaking of ordering, as we have been starting to do production deployments, I realized that my previous notion to allow developers to reorder changes in the plan file without rebuilding databases was a mistake. It was too easy for someone to deploy to an existing database and miss changes because there was nothing to notice that changes had not been deployed. This was especially a problem before I addressed the ordering issue.</p>

<p>Even with ordering fixed, I thought about how <code>git push</code> works, and <a href="/computers/databases/changing-sqitch_ids.html">realized</a> that it was much more important to make sure things really were consistent than it was to make things slightly more convenient for developers.</p>

<p>So I changed the way change IDs are generated. The text hashed for IDs now includes the ID of the parent change (if there is one), the change dependencies, and the change note. If any of these things change, the ID of the change will change. So they might change a lot during development, while one moves things arounds, changes dependencies, and tweaks the description. But the advantage is for production, where things have to be deployed exactly right, with no modifications, or else the deploy will fail. This is sort of like requiring all Git merges to be fast-forwarded, and philosophically in line with the Git practice of never changing commits after they&rsquo;re pushed to a remote repository accessible to others.</p>

<p>Curious what text is hashed for the IDs? Check out the new <a href="(https://metacpan.org/module/sqitch-show"><code>show</code> command</a>!</p>

<h3>Rebase</h3>

<p>As a database hacker, I still need things to be relatively convenient for iterative development. So I&rsquo;ve also added the <a href="https://github.com/theory/sqitch/blob/master/lib/sqitch-rebase.pod"><code>rebase</code> command</a>. It&rsquo;s simple, really: It just does a <code>revert</code> and a <code>deploy</code> a single command. I&rsquo;m doing this all day long, so I&rsquo;m happy to save myself a few steps. It&rsquo;s also nice that I can do <code>sqitch rebase @HEAD^</code> to revert and re-apply the latest change over and over again without fear that it will fail because of an ordering problem. But I already mentioned that, didn&rsquo;t I?</p>

<h3>Order Up</h3>

<p>Well, mostly. Another ordering issue I addressed was for the <code>revert --to</code> option. It used to be that it would find the change to revert to in the <em>plan</em>, and revert based on the plan order. (And did I mention that said order might have <em>changed since the last deploy?</em>) v0.940 now searches the <em>database</em> for the revert target. Not only that, the full list of changes to deploy to revert to the target is <em>also</em> returned from the database. In fact, the <code>revert</code> no longer consults the plan file at all. This is great if you&rsquo;ve re-ordered things, because the revert will <em>always</em> be the reverse order of
the <em>previous</em> deploy. Even if IDs have changed, <code>revert</code> will find the changes to revert by name. It will only fail if you&rsquo;ve removed the revert script for a change.</p>

<p>So simple, conceptually: <code>revert</code> reverts in the proper order based on what was deployed before. <code>deploy</code> deploys based on the order in the plan.</p>

<h3>Not <code>@FIRST</code>, Not <code>@LAST</code></h3>

<p>As a result of the improved intelligence of <code>revert</code>, I have also deprecated the <code>@FIRST</code> and <code>@LAST</code> symbolic tags. These tags forced a search of the database, but were mainly used for <code>revert</code>. Now that <code>revert</code> always searches the database, there&rsquo;s nothing to force. They&rsquo;re still around for backward compatibility, but no longer documented. Use <code>@ROOT</code> and <code>@HEAD</code>, instead.</p>

<h3>Not Over</h3>

<p>So lots of big changes, including some compatibility changes. But I&rsquo;ve tried hard to make them as transparent as possible (old IDs will automatically be updated by <code>deploy</code>). So take it for a spin!</p>

<p>Meanwhile, I still have quite a few other improvements I need to make. On my short list are:</p>

<ul>
<li><a href="https://github.com/theory/sqitch/issues/39">Checking all dependencies</a>  before deploying or reverting <em>any</em> changes.</li>
<li><a href="https://github.com/theory/sqitch/issues/15">Adding the <code>verify</code> command</a>  to run acceptance tests.</li>
<li><a href="https://github.com/theory/sqitch/issues/54">Adding a <code>--no-run</code> option to <code>deploy</code></a> so that existing databases can be upgraded to Sqitch.</li>
<li><a href="https://github.com/theory/sqitch/issues/13">Adding a <code>check</code> command</a> to sanity-check a plan, scripts, and a database.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/k8lSB6Kw37s" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-rebase.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/postgresql/format.html">
    <title>New in PostgreSQL 9.2: format()</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/w0wU4bJHP2g/format.html</link>
    <description />
    <dc:subject>/computers/databases/postgresql</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-11-16T01:31-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>There&rsquo;s a new feature in PostgreSQL 9.2 that I don&rsquo;t recall seeing blogged about elsewhere: the <code>format()</code> function. From <a href="http://www.postgresql.org/docs/current/static/functions-string.html">the docs</a>:</p>

<blockquote><p>Format a string. This function is similar to the C function sprintf; but only the following conversion specifications are recognized: %s interpolates the corresponding argument as a string; %I escapes its argument as an SQL identifier; %L escapes its argument as an SQL literal; %% outputs a literal %. A conversion can reference an explicit parameter position by preceding the conversion specifier with n$, where n is the argument position.</p></blockquote>

<p>If you do a lot of dynamic query building in PL/pgSQL functions, you&rsquo;ll immediately see the value in <code>format()</code>. Consider this function:</p>

<pre><code>CREATE OR REPLACE FUNCTION make_month_partition(
    base_table   TEXT,
    schema_name  TEXT,
    month        TIMESTAMP
) RETURNS VOID LANGUAGE plpgsql AS $_$
DECLARE
    partition TEXT := quote_ident(base_table || '_' || to_char(month, '"y"YYYY"m"MM'));
    month_start TIMESTAMP := date_trunc('month', month);
BEGIN
    EXECUTE '
        CREATE TABLE ' || quote_ident(schema_name) || '.' || partition || ' (CHECK (
               created_at &gt;= ' || quote_literal(month_start) || '
           AND created_at &lt; '  || quote_literal(month_start + '1 month'::interval) || '
        )) INHERITS (' || quote_ident(schema_name) || '.' || base_table || ')
    ';
    EXECUTE 'GRANT SELECT ON ' || quote_ident(schema_name) || '.' || partition || '  TO dude;';
END;
$_$;
</code></pre>

<p>Lots of concatenation and use of <code>quote_ident()</code> to get things just right. I don&rsquo;t know about you, but I always found this sort of thing quite difficult to read. But <code>format()</code> allows use to eliminate most of the operators and function calls. Check it:</p>

<pre><code>CREATE OR REPLACE FUNCTION make_month_partition(
    base_table   TEXT,
    schema_name  TEXT,
    month        TIMESTAMP
) RETURNS VOID LANGUAGE plpgsql AS $_$
DECLARE
    partition TEXT := base_table || '_' || to_char(month, '"y"YYYY"m"MM');
    month_start TIMESTAMP := date_trunc('month', month);
BEGIN
    EXECUTE format(
        'CREATE TABLE %I.%I (
            CHECK (created_at &gt;= %L AND created_at &lt; %L)
        ) INHERITS (%I.%I)',
        schema_name, partition,
        month_start, month_start + '1 month'::interval,
        schema_name, base_table
    );
    EXECUTE format('GRANT SELECT ON %I.%I TO dude', schema_name, partition);
END;
$_$;
</code></pre>

<p>I don&rsquo;t know about you, but I find that a <em>lot</em> easier to read. which means it&rsquo;ll be easier to maintain. So if you do much dynamic query generation inside the database, give <code>format()</code> a try, I think you&rsquo;ll find it a winner.</p>

<p><em><strong>Update 2012-11-16:</strong> Okay, so I somehow failed to notice that <code>format()</code> was actually introduced in 9.1 and <a href="http://www.depesz.com/2010/11/21/waiting-for-9-1-format/">covered by depesz</a>. D&rsquo;oh! Well, hopefully my little post will help to get the word out more, at least. Thanks to my commenters.</em></p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/w0wU4bJHP2g" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/postgresql/format.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/changing-sqitch_ids.html">
    <title>Thinking about Changing Sqitch Change IDs</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/JF6ObW7SSlE/changing-sqitch_ids.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-11-14T01:46-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>When <a href="http://sqitch.org/">Sqitch</a>, (the database change management app I&rsquo;ve been working on for the last several months) parses a deployment plan, it creates a unique ID for each change in the plan. This ID is a SHA1 hash generated from information about the change, which is a string that looks something like this:</p>

<pre><code>project flipr
change add_users_table
planner Marge N. O’Vera &lt;marge@example.com&gt;
date 2012-11-14T01:10:13Z
</code></pre>

<p>The nice thing about the ID is that it&rsquo;s unique: it&rsquo;s unlikely that the same user with the same email address will add a change with the same name to a project with the same name within a single second. If the plan includes a URI, that&rsquo;s included, too, for additional uniqueness.</p>

<p>Note, however, that it does not include information about any other changes. Git, from which I modeled the generation of these IDS, always includes the parent commit SHA1 in its uniquely-identifying info. An example:</p>

<pre><code>&gt; git cat-file commit 744c01bfa3798360c1792a8caf784b650e52d89e               
tree d3a64897cca4538ff5c0c41db3f82ab033a09bec
parent 482a79ae2cda5085eed731be2e70739ab37997ee
author David E. Wheeler &lt;david@justatheory.com&gt; 1337355746 -0400
committer David E. Wheeler &lt;david@justatheory.com&gt; 1337355746 -0400

Timestamp v0.30.
</code></pre>

<p>The reason Git does this is so that a commit is not just uniquely identified globally, but so that it can <em>only follow an existing commit</em>. Mark Jason Dominus calls this <a href="http://perl.plover.com/yak/git/">Linus Torvalds' greatest invention</a>. Why? This is now Git knows it can fast-forward changes.</p>

<p>Why doesn&rsquo;t Sqitch do something similar? My original thinking had been to make it easier for a database developer to do iterative development. And one of the requirements for that, in my experience, is the ability to freely reorder changes in the plan. Including the SHA1 of the preceding change would make that trickier. But it also means that, when you deploy to a production database, you lose that extra layer of security that ensures that, yes, the next change <em>really should be deployed</em>. That is, it would be much harder to deploy with changes missing or changed from what was previously expected. And I think that&rsquo;s only sane for a production environment.</p>

<p>Given that, I&rsquo;ve started to rethink my decision to omit the previous change SHA1 from the identifier of a change. Yes, it could be a bit more of hassle for a developer, but not, I think, <em>that</em> much of a hassle. The main thing would be to allow <code>revert</code>s to look up their scripts just by change name or even file name, rather than ID. We <em>want</em> deploys to always be correct, but I&rsquo;m thinking that reverts should always just try very hard to remove changes. Even in production.</p>

<p>I am further thinking that the ID should even include the list of prerequisite changes for even stronger identification. After all, one might change just the dependencies and nothing else, but it would <em>still</em> be a different change. And maybe it should include the note, too? The end result would be a hash of something like this:</p>

<pre><code>project flipr
change add_users_table
parent 7cd96745746cd6baa5da352de782354b21838b25
requires [schemas roles common:utils]
planner Marge N. O’Vera &lt;marge@example.com&gt;
date 2012-11-14T01:10:13Z

Adds the users table to the database.
</code></pre>

<p>This will break existing installations, so I&rsquo;d need to add a way to update them, but otherwise, I think it might be a win overall. Thoughts?</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/JF6ObW7SSlE" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/changing-sqitch_ids.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/postgresql/mock-serialization-failures.html">
    <title>Mocking Serialization Failures</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/2zEfLFqauyM/mock-serialization-failures.html</link>
    <description />
    <dc:subject>/computers/databases/postgresql</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-11-02T22:16-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>I&rsquo;ve been hacking on the forthcoming
<a href="http://bucardo.org/wiki/Bucardo">Bucardo</a> 5 code base the last couple weeks,
as we&rsquo;re going to start using it pretty extensively at
<a href="http://iovation.com/">work</a>, and it needed a little love to get it closer to
release. The biggest issue I fixed was the handling of serialization failures.</p>

<p>When copying deltas from one database to another, Bucardo sets the
<a href="http://www.postgresql.org/docs/current/static/transaction-iso.html">transaction isolation</a>
to &ldquo;Serializable&rdquo;. As of PostgreSQL 9.1, this is true serializable isolation.
However, there were no tests for it in Bucardo. And since pervious versions of
PostgreSQL had poorer isolation (retained in 9.1 as &ldquo;Repeatable Read&rdquo;), I
don&rsquo;t think anyone really noticed it much. As I&rsquo;m doing all my testing against
9.2, I was getting the serialization failures about half the time I ran the
test suite. It took me a good week to chase down the issue. Once I did, I
posted to the Bucardo mail list pointing out that Bucardo was <em>not</em> attempting
to run a transaction again after failure, and at any rate, the model for how
it thought to do so was a little wonky: it let the replicating process die, on
the assumption that a new process would pick up where it left off. It did not.</p>

<p>Bucardo maintainer Greg Sabino Mullane
<a href="https://mail.endcrypt.com/pipermail/bucardo-general/2012-October/001616.html">proposed</a>
that we let the replicating process try again on its own. So I went and made
it do that. And then the tests started passing every time. Yay!</p>

<p>Returning to the point of this post, I felt that there ought to be tests for
serialization failures in the Bucardo test suite, so that we can ensure that
this continues to work. My first thought was to use PL/pgSQL in 8.4 and higher
to mock a serialization failure. Observe:</p>

<pre><code>david=# \set VERBOSITY verbose
david=# DO $$BEGIN RAISE EXCEPTION 'Serialization error'
       USING ERRCODE = 'serialization_failure'; END $$;
ERROR:  40001: Serialization error
LOCATION:  exec_stmt_raise, pl_exec.c:2840
</code></pre>

<p>Cool, right? Well, the trick is to get this to run on the replication target,
but only once. When Bucardo retries, we want it to succeed, thus properly
demonstrating the COPY/SERIALIZATION FAIL/ROLLBACK/COPY/SUCCESS pattern.
Furthermore, when it copies deltas to a target, Bucardo disables all triggers
and rules. So how to get something trigger-like to run on a target table and
throw the serialization error?</p>

<p>Studying the Bucardo source code, I discovered that Bucardo itself does not
disable triggers and rules. Rather, it sets the <code>session_replica_role</code> GUC to
&ldquo;replica&rdquo;. This causes PostgreSQL to disable the triggers and rules &mdash; except
for those that have been set to <code>ENABLE REPLICA</code>. The PostgreSQL
<a href="http://www.postgresql.org/docs/9.2/static/sql-altertable.html"><code>ALTER TABLE</code> docs</a>:</p>

<blockquote><p>The trigger firing mechanism is also affected by the configuration
variable session_replication_role. Simply enabled triggers will
fire when the replication role is &ldquo;origin&rdquo; (the default) or
&ldquo;local&rdquo;. Triggers configured as ENABLE REPLICA will only fire if the
session is in &ldquo;replica&rdquo; mode, and triggers configured as ENABLE ALWAYS
will fire regardless of the current replication mode.</p></blockquote>

<p>Well how cool is that? So all I needed to do was plug in a replica trigger and have it throw an exception once but not twice. Via email, Kevin Grittner pointed out that a sequence might work, and indeed it does. Because sequence values are non-transactional, sequences return different values every time they&rsquo;re access.</p>

<p>Here&rsquo;s what I came up with:</p>

<pre><code>CREATE SEQUENCE serial_seq;

CREATE OR REPLACE FUNCTION mock_serial_fail(
) RETURNS trigger LANGUAGE plpgsql AS $_$
BEGIN
    IF nextval('serial_seq') % 2 = 0 THEN RETURN NEW; END IF;
    RAISE EXCEPTION 'Serialization error'
          USING ERRCODE = 'serialization_failure';
END;
$_$;

CREATE TRIGGER mock_serial_fail AFTER INSERT ON bucardo_test2
    FOR EACH ROW EXECUTE PROCEDURE mock_serial_fail();
ALTER TABLE bucardo_test2 ENABLE REPLICA TRIGGER mock_serial_fail;
</code></pre>

<p>The first <code>INSERT</code> (or, in Bucardo&rsquo;s case, <code>COPY</code>) to <code>bucardo_test2</code> will die
with the serialization error. The second <code>INSERT</code> (or <code>COPY</code>) succeeds. This
worked great, and I was able to write test in a few hours and
<a href="https://github.com/bucardo/bucardo/commit/3931056f15f3f6df9b089fd439c14ec38b66d841">get them committed</a>.
And now we can be reasonably sure that Bucardo will always properly handle
serialization failures.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/2zEfLFqauyM" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/postgresql/mock-serialization-failures.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/programming/perl/modules/dist-zilla-localetextdomain.html">
    <title>Localize Your Perl modules with Locale::TextDomain and Dist::Zilla</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/PWpbyHlAOi8/dist-zilla-localetextdomain.html</link>
    <description />
    <dc:subject>/computers/programming/perl/modules</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-10-01T20:50-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>I've just released <a href="https://metacpan.org/release/Dist-Zilla-LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a> v0.80 to the CPAN. This module adds support for managing <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a>-based localization and internationalization in your CPAN libraries. I wanted to make it as simple as possible for CPAN developers to do localization and to support translators in their projects, and <a href="https://metacpan.org/module/Dist::Zilla">Dist::Zilla</a> seemed like the perfect place to do it, since it has hooks to generate the necessary binary files for distribution.</p>

<p>Starting out with Locale::TextDomain was decidedly non-intuitive for me, as a Perl hacker, likely because of its <a href="http://www.gnu.org/software/gettext/">gettext</a> underpinnings. Now that I've got a grip on it and created the Dist::Zilla support, I think it's pretty straight-forward. To demonstrate, I wrote the following brief tutorial, which constitutes the main documentation for the <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">Dist::Zilla::LocaleTextDomain</a> distribution. I hope it makes it easier for you to get started localizing your Perl libraries.</p>

<h3>Localize Your Perl modules with Locale::TextDomain and Dist::Zilla</h3>

<p><a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> provides a nice interface for localizing your Perl applications. The tools for managing translations, however, is a bit arcane. Fortunately, you can just use <a href="https://metacpan.org/module/Dist::Zilla::LocaleTextDomain">this plugin</a> and get all the tools you need to scan your Perl libraries for localizable strings, create a language template, and initialize translation files and keep them up-to-date. All this is assuming that your system has the <a href="http://www.gnu.org/software/gettext/">gettext</a> utilities installed.</p>

<h4 id="The-Details">The Details</h4>

<p>I put off learning how to use <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> for quite a while because, while the <a href="http://www.gnu.org/software/gettext/">gettext</a> tools are great for translators, the tools for the developer were a little more opaque, especially for Perlers used to <a href="https://metacpan.org/module/Locale::Maketext">Locale::Maketext</a>. But I put in the effort while hacking <a href="https://metacpan.org/module/App::Sqitch">Sqitch</a>. As I had hoped, using it in my code was easy. Using it for my distribution was harder, so I decided to write Dist::Zilla::LocaleTextDomain to make life simpler for developers who manage their distributions with <a href="https://metacpan.org/module/Dist::Zilla">Dist::Zilla</a>.</p>

<p>What follows is a quick tutorial on using <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> in your code and managing it with Dist::Zilla::LocaleTextDomain.</p>

<h4 id="This-is-my-domain">This is my domain</h4>

<p>First thing to do is to start using <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> in your code. Load it into each module with the name of your distribution, as set by the <code>name</code> attribute in your <i>dist.ini</i> file. For example, if your <i>dist.ini</i> looks something like this:</p>

<pre><code>name    = My-GreatApp
author  = Homer Simpson &lt;homer@example.com&gt;
license = Perl_5</code></pre>

<p>Then, in you Perl libraries, load <a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> like this:</p>

<pre><code>use Locale::TextDomain qw(My-GreatApp);</code></pre>

<p><a href="https://metacpan.org/module/Locale::TextDomain">Locale::TextDomain</a> uses this value to find localization catalogs, so naturally Dist::Zilla::LocaleTextDomain will use it to put those catalogs in the right place.</p>

<p>Okay, so it&#39;s loaded, how do you use it? The documentation of the <a href="https://metacpan.org/module/Locale::TextDomain#EXPORTED-FUNCTIONS">Locale::TextDomain exported functions</a> is quite comprehensive, and I think you&#39;ll find it pretty simple once you get used to it. For example, simple strings are denoted with <code>__</code>:</p>

<pre><code>say __ &#39;Hello&#39;;</code></pre>

<p>If you need to specify variables, use <code>__x</code>:</p>

<pre><code>say __x(
    &#39;You selected the color {color}&#39;,
    color =&gt; $color
);</code></pre>

<p>Need to deal with plurals? Use <code>__n</code></p>

<pre><code>say __n(
    &#39;One file has been deleted&#39;,
    &#39;All files have been deleted&#39;,
    $num_files,
);</code></pre>

<p>And then you can mix variables with plurals with <code>__nx</code>:</p>

<pre><code>say __nx(
    &#39;One file has been deleted.&#39;,
    &#39;{count} files have been deleted.&#39;&quot;,
    $num_files,
    count =&gt; $num_files,
);</code></pre>

<p>Pretty simple, right? Get to know these functions, and just make it a habit to use them in user-visible messages in your code. Even if you never expect to translate those messages, just by doing this you make it easier for someone else to come along and start translating for you.</p>

<h5 id="The-setup">The setup</h5>

<p>Now you&#39;re localizing your code. Great! What&#39;s next? Officially, nothing. If you never do anything else, your code will always emit the messages as written. You can ship it and things will work just as if you had never done any localization.</p>

<p>But what&#39;s the fun in that? Let&#39;s set things up so that translation catalogs will be built and distributed once they&#39;re written. Add these lines to your <i>dist.ini</i>:</p>

<pre><code>[ShareDir]
[LocaleTextDomain]</code></pre>

<p>There are actually quite a few attributes you can set here to tell the plugin where to find language files and where to put them. For example, if you used a domain different from your distribution name, e.g.,</p>

<pre><code>use Locale::TextDomain &#39;com.example.My-GreatApp&#39;;</code></pre>

<p>Then you would need to set the <code>textdomain</code> attribute so that the <code>LocaleTextDomain</code> does the right thing with the language files:</p>

<pre><code>[LocaleTextDomain]
textdomain = com.example.My-GreatApp</code></pre>

<p>Consult the <a href="https://metacpan.org/module/Dist::Zilla::Plugin::LocaleTextDomain#Configuration"><code>LocaleTextDomain</code> configuration docs</a> for details on all available attributes.</p>

<blockquote><p>(Special note until <a href="https://rt.cpan.org/Public/Bug/Display.html?id=79461">this Locale::TextDomain patch</a> is merged: set the <code>share_dir</code> attribute to <code>lib</code> instead of the default value, <code>share</code>. If you use <a href="https://metacpan.org/module/Module::Build">Module::Build</a>, you will also need a subclass to do the right thing with the catalog files; see <a href="https://metacpan.org/module/Dist::Zilla::Plugin::LocaleTextDomain#Installation">&quot;Installation&quot; in Dist::Zilla::Plugin::LocaleTextDomain</a> for details.)</p></blockquote>

<p>What does this do including the plugin do? Mostly nothing. You might see this line from <code>dzil build</code>, though:</p>

<pre><code>[LocaleTextDomain] Skipping language compilation: directory po does not exist</code></pre>

<p>Now at least you know it was looking for something to compile for distribution. Let&#39;s give it something to find.</p>

<h5 id="Initialize-languages">Initialize languages</h5>

<p>To add translation files, use the <a href="https://metacpan.org/module/Dist::Zilla::App::Command::msg_init"><code>msg-init</code></a> command:</p>

<pre><code>&gt; dzil msg-init de
Created po/de.po.</code></pre>

<p>At this point, the <a href="http://www.gnu.org/software/gettext/">gettext</a> utilities will need to be installed and visible in your path, or else you&#39;ll get errors.</p>

<p>This command scans all of the Perl modules gathered by Dist::Zilla and initializes a German translation file, named <i>po/de.po</i>. This file is now ready for your German-speaking public to start translating. Check it into your source code repository so they can find it. Create as many language files as you like:</p>

<pre><code>&gt; dzil msg-init fr ja.JIS en_US.UTF-8
Created po/fr.po.
Created po/ja.po.
Created po/en_US.po.</code></pre>

<p>As you can see, each language results in the generation of the appropriate file in the <i>po</i> directory, sans encoding (i.e., no <i>.UTF-8</i> in the <code>en_US</code> file name).</p>

<p>Now let your translators go wild with all the languages they speak, as well as the regional dialects. (Don&#39;t forget to colour your code with <code>en_UK</code> translations!)</p>

<p>Once you have translations and they&#39;re committed to your repository, when you build your distribution, the language files will automatically be compiled into binary catalogs. You&#39;ll see this line output from <code>dzil build</code>:</p>

<pre><code>[LocaleTextDomain] Compiling language files in po
po/fr.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.
po/ja.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.
po/en_US.po: 10 translated messages, 1 fuzzy translation, 0 untranslated messages.</code></pre>

<p>You&#39;ll then find the catalogs in the shared directory of your distribution:</p>

<pre><code>&gt; find My-GreatApp-0.01/share -type f
My-GreatApp-0.01/share/LocaleData/de/LC_MESSAGES/App-Sqitch.mo
My-GreatApp-0.01/share/LocaleData/en_US/LC_MESSAGES/App-Sqitch.mo
My-GreatApp-0.01/share/LocaleData/ja/LC_MESSAGES/App-Sqitch.mo</code></pre>

<p>These binary catalogs will be installed as part of the distribution just where <code>Locale::TextDomain</code> can find them.</p>

<p>Here&#39;s an optional tweak: add this line to your <code>MANIFEST.SKIP</code>:</p>

<pre><code>^po/</code></pre>

<p>This prevents the <i>po</i> directory and its contents from being included in the distribution. Sure, you can include them if you like, but they&#39;re not required for the running of your app; the generated binary catalog files are all you need. Might as well leave out the translation files.</p>

<h5 id="Mergers-and-acquisitions">Mergers and acquisitions</h5>

<p>You&#39;ve got translation files and helpful translators given them a workover. What happens when you change your code, add new messages, or modify existing ones? The translation files need to periodically be updated with those changes, so that your translators can deal with them. We got you covered with the <a href="https://metacpan.org/module/Dist::Zilla::App::Command::msg_merge"><code>msg-merge</code></a> command:</p>

<pre><code>&gt; dzil msg-merge
extracting gettext strings
Merging gettext strings into po/de.po
Merging gettext strings into po/en_US.po
Merging gettext strings into po/ja.po</code></pre>

<p>This will scan your module files again and update all of the translation files with any changes. Old messages will be commented-out and new ones added. Just commit the changes to your repository and notify the translation army that they&#39;ve got more work to do.</p>

<p>If for some reason you need to update only a subset of language files, you can simply list them on the command-line:</p>

<pre><code>&gt; dzil msg-merge po/de.po po/en_US.po
Merging gettext strings into po/de.po
Merging gettext strings into po/en_US.po</code></pre>

<h5 id="Whats-the-scan-man">What&#39;s the scan, man</h5>

<p>Both the <code>msg-init</code> and <code>msg-merge</code> commands depend on a translation template file to create and merge language files. Thus far, this has been invisible: they will create a temporary template file to do their work, and then delete it when they&#39;re done.</p>

<p>However, it&#39;s common to also store the template file in your repository and to manage it directly, rather than implicitly. If you&#39;d like to do this, the <a href="https://metacpan.org/module/Dist::Zilla::App::Command::msg_scan"><code>msg-scan</code></a> command will scan the Perl module files gathered by Dist::Zilla and make it for you:</p>

<pre><code>&gt; dzil msg-scan
gettext strings into po/My-GreatApp.pot</code></pre>

<p>The resulting <i>.pot</i> file will then be used by <code>msg-init</code> and <code>msg-merge</code> rather than scanning your code all over again. This actually then makes <code>msg-merge</code> a two-step process: You need to update the template before merging. Updating the template is done by exactly the same command, <code>msg-scan</code>:</p>

<pre><code>&gt; dzil msg-scan
extracting gettext strings into po/My-GreatApp.pot
&gt; dzil msg-merge
Merging gettext strings into po/de.po
Merging gettext strings into po/en_US.po
Merging gettext strings into po/ja.po</code></pre>

<h5 id="Ship-It-">Ship It!</h5>

<p>And that&#39;s all there is to it. Go forth and localize and internationalize your Perl apps!</p>

<h3>Acknowledgements</h3>

My thanks to <a href="http://rjbs.manxome.org">Ricardo Signes</a> for invaluable help plugging in to Dist::Zilla, to <a href="http://guido-flohr.net/">Guido Flohr</a> for providing feedback on this tutorial and being open to my pull requests, to <a href="http://www.dagolden.com/">David Golden</a> for I/O capturing help, and to <a href="https://metacpan.org/author/JQUELIN">Jérôme Quelin</a> for his patience as I wrote code to do the same thing as <a href="https://metacpan.org/module/Dist::Zilla::Plugin::LocaleMsgfmt">Dist::Zilla::Plugin::LocaleMsgfmt</a> without ever noticing that it already existed.</p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/PWpbyHlAOi8" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/programming/perl/modules/dist-zilla-localetextdomain.html</feedburner:origLink></item>
  <item rdf:about="http://justatheory.com/computers/databases/sqitch-symbolism.html">
    <title>Sqitch Symbolism</title>
    <link>http://feedproxy.google.com/~r/justatheory/rssfull/~3/9dPugsFK1x8/sqitch-symbolism.html</link>
    <description />
    <dc:subject>/computers/databases</dc:subject>
    <dc:creator>David E. Wheeler</dc:creator>
    <dc:date>2012-09-25T22:59-09:00</dc:date>
    
    <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc/2.0" />
    <content:encoded><![CDATA[<p>It has been a while since I <a href="/computers/databases/sqitch-depend-on-it.html">last blogged about Sqitch</a>. The silence is in part due to the fact that I&rsquo;ve moved from full-time Sqitch development to actually putting it to use building databases at work. This is exciting, because it needs the real-world experience to grow up.</p>

<p>That&rsquo;s not to say that nothing has happened with Sqitch. I&rsquo;ve just released <a href="https://metacpan.org/release/DWHEELER/App-Sqitch-0.931/">v0.931</a> which includes a bunch of improvement since I wrote about v0.90. First a couple of the minor things:</p>

<ul>
<li>Sqitch now checks dependencies before reverting, and dies if they would be broken by the revert. This change, introduced in v0.91, required that the dependencies be moved to their own table, so if you&rsquo;ve been messing with an earlier version of Sqitch, you&rsquo;ll have to rebuild the database. Sorry about that.</li>
<li>I fixed a bunch of Windows-related issues, including finding the current user&rsquo;s full name, correctly setting the locale for displaying dates and times, executing shell commands, and passing tests. The awesome <a href="http://code.activestate.com/ppm/App-Sqitch/">ActiveState PPM Index</a> has been invaluable in tracking these issues down.</li>
<li>Added the <a href="https://metacpan.org/module/sqitch-bundle"><code>bundle</code> command</a>. All it does is copy your project configuration file, plan, and deploy, revert, and test scripts to a directory you identify. The purpose is to be able to export the project into a directory structure suitable for distribution in a tarball, RPM, or whatever. That my not sound incredibly useful, since copying files is no big deal. However, the long-term plan is to add VCS support to Sqitch, which would entail fetching scripts from various places in VCS history. At that point, it will be essential to use <code>bundle</code> to do the export, so that scripts are properly exported from the VCS history. That said, I&rsquo;m actually using it already to build RPMs. Useful already!</li>
</ul>


<h3>Symbolic References</h3>

<p>And now the more immediately useful changes. First, I added new symbolic tags,  <code>@FIRST</code> and <code>@LAST</code>. These represent the first and last changes currently deployed to a database, respectively. These complement the existing <code>@ROOT</code> and <code>@HEAD</code> symbolic tags, which represent the first and last changes listed in the <em>plan.</em> The distinction is important: The change plan vs actual deployments to a database.</p>

<p>The addition of <code>@FIRST</code> and <code>@LAST</code> may not sounds like much, but there&rsquo;s more.</p>

<p>I also added forward and reverse change reference modifiers <code>^</code> and <code>~</code>. The basic idea was stolen from <a href="http://git-scm.com/docs/gitrevisions">Git Revisions</a>, though the semantics vary. For <a href="https://metacpan.org/module/sqitchchanges">Sqitch changes</a>, <code>^</code> appended to a name or tag means &ldquo;the change before this change,&rdquo; while <code>~</code> means &ldquo;the change after this change&rdquo;. I find <code>^</code> most useful when doing development, where I&rsquo;m constantly deploying and reverting a change as I work. Here&rsquo;s how I do that revert:</p>

<pre><code>sqitch revert --to @LAST^
</code></pre>

<p>That means &ldquo;revert to the change before the last change&rdquo;, or simply &ldquo;revert the last change&rdquo;. If I want to revert two changes, I use two <code>^</code>s:</p>

<pre><code>sqitch revert --to @LAST^^
</code></pre>

<p>To go back any further, I need to use an integer with the <code>^</code>. Here&rsquo;s how to revert the last four changes deployed to the database:</p>

<pre><code>sqitch revert --to @LAST^4
</code></pre>

<p>The cool thing about this is that I don&rsquo;t have to remember the name of the change to revert, as was previously required. And of course, if I just wanted to deploy two changes since the last deployment, I would use <code>~~</code>:</p>

<pre><code>sqitch deploy --to @LAST~~
</code></pre>

<p>Nice, right? One thing to bear in mind, as I was reminded while giving a <a href="http://www.slideshare.net/justatheory/sane-sql-change-management-with-sqitch">Sqitch presentation</a> to <a href="http://pdxpug.wordpress.com/2012/09/07/pdxpug-september-meeting-coming-up/">PDXPUG</a>: Changes are deployed in a sequence. You can think of them as a linked list. So this command:</p>

<pre><code>sqitch revert @LAST^^
</code></pre>

<p>Does <em>not</em> mean to revert the second-to-last change, leaving the two after it. It will revert the last change <em>and</em> the penultimate change. This is why I actually encourage the use of the <code>--to</code> option, to emphasize that you&rsquo;re deploying or reverting all changes <em>to</em> the named point, rather than deploying or reverting the named point in isolation. Sqitch simply doesn&rsquo;t do that.</p>

<h3>Internationalize Me</h3>

<p>One more change. With today&rsquo;s release of v0.931, there is now proper internationalization support in Sqitch. The code has been localized for a long time, but there was no infrastructure for internationalizing. Now there is, and I&rsquo;ve stubbed out files for translating Sqitch messages into <a href="https://github.com/theory/sqitch/blob/master/po/fr.po">French</a> and <a href="https://github.com/theory/sqitch/blob/master/po/de.po">German</a>. Adding others is easy.</p>

<p>If you&rsquo;re interested in tranlating Sqitch&rsquo;s messages (only 163 of them, should be quick!), just <a href="https://github.com/theory/sqitch/">fork Sqitch</a>, juice up your favorite <a href="http://www.google.com/search?q=gettext+editor">gettext editor</a>, and start editing. Let me know if you need a language file generated; I&rsquo;ve built the tools to do it easily with <a href="http://dzil.org/">dzil</a>, but haven&rsquo;t released them yet. Look for a post about that later in the week.</p>

<h3>Presentation</h3>

<p>Oh, and that <a href="http://pdxpug.wordpress.com/2012/09/07/pdxpug-september-meeting-coming-up/">PDXPUG presentation</a>? Here are the slides. Enjoy!</p>

<iframe src="http://www.slideshare.net/slideshow/embed_code/14459486" width="597" height="486" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen> </iframe>


<p> <div style="margin-bottom:5px"> <strong> <a href="http://www.slideshare.net/justatheory/sane-sql-change-management-with-sqitch" title="Sane SQL Change Management with Sqitch" target="_blank">Sane SQL Change Management with Sqitch</a> </strong> from <strong><a href="http://www.slideshare.net/justatheory" target="_blank">David E. Wheeler</a></strong> </div></p>
<img src="http://feeds.feedburner.com/~r/justatheory/rssfull/~4/9dPugsFK1x8" height="1" width="1"/>]]></content:encoded>
  <feedburner:origLink>http://justatheory.com/computers/databases/sqitch-symbolism.html</feedburner:origLink></item>
  <cc:License rdf:about="http://creativecommons.org/licenses/by-nc/2.0/">
    <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction" />
    <cc:permits rdf:resource="http://web.resource.org/cc/Distribution" />
    <cc:requires rdf:resource="http://web.resource.org/cc/Notice" />
    <cc:requires rdf:resource="http://web.resource.org/cc/Attribution" />
    <cc:prohibits rdf:resource="http://web.resource.org/cc/CommercialUse" />
    <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
  </cc:License>
</rdf:RDF>
