<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atomfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://purl.org/atom/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" version="0.3">

<title type="text/plain">Just a Theory</title>
<tagline type="text/plain">Theory waxes practical. By David Wheeler.</tagline>
<link rel="alternate" type="text/html" href="http://www.justatheory.com" />
<id>tag:justatheory.com,2009:/</id>
<generator url="http://www.blosxom.com/" version="2.1">Blosxom</generator>

<link rel="start" href="http://feeds.feedburner.com/justatheory" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/testing-td-views</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/testing-td-views.html" />
<title type="text/plain">Testing Catalyst Template::Declare Views</title>
<dc:subject>Catalyst</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>view</dc:subject>
<dc:subject>tests</dc:subject>
<dc:subject>testing</dc:subject>
<dc:subject>Test::XPath</dc:subject>
<issued>2009-11-10T18:01:00Z</issued>
<modified>2009-11-10T18:01:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Now that we have our default Catalyst <a href="http://www.justatheory.com/computers/programming/perl/catalyst/testing.html" title="Testing the Tutorial App">tests passing</a>, let's have a look at testing the views we've created. You can follow along via the <a href="http://github.com/theory/catalyst-tutorial/commits/part-06">Part 6 tag</a> tag in the GitHub repository. Start by looking at the default test script for our HTML view, <code>t/view_HTML.t</code>. It should look something like this:</p>

<pre>
use strict;
use warnings;
use Test::More tests =&gt; 3;
# use Test::XPath;

BEGIN {
    use_ok 'MyApp::View::HTML' or die;
    use_ok 'MyApp' or die;
}

ok my $view = MyApp-&gt;view('HTML'), 'Get HTML view object';

# ok my $output = $view-&gt;render(undef, 'hello', { user =&gt; 'Theory' }),
#     'Render the "hello" template';

# Test output using Test::XPath or similar.
# my $tx = Test::XPath-&gt;new( xml =&gt; $output, is_html =&gt; 1);
# $tx-&gt;ok('/html', 'Should have root html element');
# $tx-&gt;is('/html/head/title', 'Hello, Theory', 'Title should be correct');
</pre>

<p>Yeah, this looks a bit different that the view test created for Template Toolkit or Mason views. That's because <a href="http://search.cpan.org/dist/Catalyst-View-TD" title="Catalyst::View::TD on CPAN">Catalyst::View::TD</a> ships with its own test script template. One of the advantage is that it shows off testing the view without having to instantiate the entire app or send mock HTTP requests. These are unit tests, after all: we want to make sure that the view templates do what they want, not test an entire request process. The latter is more appropriate for integration tests, which I'll cover later.</p>

<p>So let's have a look at this test script. The first commented-out statement is:</p>

<pre>
# ok my $output = $view-&gt;render(undef, 'hello', { user =&gt; 'Theory' }),
#     'Render the "hello" template';
</pre>

<p>What this is showing us is that one can use the view's <code>render()</code> method to execute a view without a context object, thus saving the expense of initializing the application. And if you have templates that don't rely on it, I highly recommend this approach for keeping your tests fast. Even if the use of the the context object is fairly minimal, you can use <a href="http://search.cpan.org/perldoc?Test::MockObject" title="Test::MockObject on CPAN">Test::MockObject</a> to mock up a context object like so:</p>

<pre>
use Test::MockObject;
my $c = Test::MockObject-&gt;new;
$c-&gt;mock(uri_for =&gt; sub { $_[1] });
$c-&gt;mock(config  =&gt; sub { { name =&gt; 'MyApp' } });
$c-&gt;mock(debug   =&gt; sub { });
$c-&gt;mock(log     =&gt; sub { });

ok my $output = $view-&gt;render($c, 'hello', { user =&gt; 'Theory' }),
     'Render the "hello" template';
</pre>

<p>Then you can use the <code>mock()</code> method to mock more methods as your template uses them.</p>

<p>Alas, our app has already passed the point where that seems worthwhile. So far we have just one template, <code>books/list</code>, and it requires that there also be a database statement handle available. Sure we could create a database connection and prepare a statement handle. But that would start to require a fair bit more code to set up. So let's just instantiate the application object and be done with it. Change the test plan to 5:</p>

<pre>
use Test::More tests =&gt; 5;
</pre>

<p>Then change the test body after the <code>BEGIN</code> block to:</p>

<pre>
# Instantiate the context object and the view.
ok my $c = MyApp-&gt;new, 'Create context object';
ok my $view = $c-&gt;view('HTML'), 'Get HTML view object';

# Create a statement handle for books/list.
my $sth = $c-&gt;conn-&gt;run(sub { $_-&gt;prepare(q{
    SELECT isbn, title, rating, authors FROM books_with_authors
}) });
$sth-&gt;execute;

# Render books/list.
ok my $output = $view-&gt;render($c, 'books/list', {
    title =&gt; 'Book List',
    books =&gt; $sth,
}), 'Render the "books/list" template';
</pre>

<p>This allows us to get a full test of the view. </p>

<pre>
% prove --lib --verbose t/view_HTML.t
t/view_HTML.t .. 
1..5
ok 1 - use MyApp::View::HTML;
ok 2 - use MyApp;
ok 3 - Create context object
ok 4 - Get HTML view object
Explicit blessing to '' (assuming package main) at /usr/local/lib/perl5/site_perl/5.10.1/Catalyst.pm line 1281.
Explicit blessing to '' (assuming package main) at /usr/local/lib/perl5/site_perl/5.10.1/Catalyst.pm line 1281.
Explicit blessing to '' (assuming package main) at /usr/local/lib/perl5/site_perl/5.10.1/Catalyst.pm line 1281.
Explicit blessing to '' (assuming package main) at /usr/local/lib/perl5/site_perl/5.10.1/Catalyst.pm line 1281.
ok 5 - Render the "books/list" template
ok
All tests successful.
Files=1, Tests=5,  1 wallclock secs ( 0.02 usr  0.00 sys +  0.69 cusr  0.06 csys =  0.77 CPU)
Result: PASS
</pre>

<p>Hrm. Those warnings are rather annoying. Looking at <code>Catalyst.pm</code> I see that they come from the <code>uri_for()</code> method. I expect that they somehow result from a lack of state in the context object. That's not really important for our unit tests, so let's just mock that one method to do something reasonable. Add this code after instantiating the context object but before rendering the view:</p>

<pre>
use Test::MockObject::Extends;
my $mocker = Test::MockObject::Extends-&gt;new($c);
$mocker-&gt;mock( uri_for =&gt; sub { $_[1]} );
</pre>

<p>And now we get:</p>

<pre>
% prove --lib --verbose t/view_HTML.t
t/view_HTML.t .. 
1..5
ok 1 - use MyApp::View::HTML;
ok 2 - use MyApp;
ok 3 - Create context object
ok 4 - Get HTML view object
ok 5 - Render the "books/list" template
ok
All tests successful.
Files=1, Tests=5,  1 wallclock secs ( 0.02 usr  0.01 sys +  0.77 cusr  0.07 csys =  0.87 CPU)
Result: PASS
</pre>

<p>Ah, much better! And thanks to our mock, we also have a much better idea of what will be returned from <code>uri_for()</code>, which will be important for later tests.</p>

<p>Now that we have things properly mocked up and the objects created such that we can actually get the template to render, it's time to test the output from the template. For HTML and XML format, I like the <a href="http://search.cpan.org/perldoc?Test::XPath" title="Test::XPath on CPAN">Test::XPath</a> module. In fact, it's for this very use that I wrote Test::XPath. It's great because it allows me to effectively test the correctness of the template output. Here's the basic outline:</p>

<pre>
# Test output using Test::XPath.
my $tx = Test::XPath-&gt;new( xml =&gt; $output, is_html =&gt; 1);
test_basics($tx, 'Book List');

# Call this function for every request to make sure that they all
# have the same basic structure.
sub test_basics {
    my ($tx, $title) = @_;

    # Some basic sanity-checking.
    $tx-&gt;is( 'count(/html)',      1, 'Should have 1 html element' );
    $tx-&gt;is( 'count(/html/head)', 1, 'Should have 1 head element' );
    $tx-&gt;is( 'count(/html/body)', 1, 'Should have 1 body element' );

    # Check the head element.
    $tx-&gt;is(
        '/html/head/title',
        $title,
        'Title should be corect'
    );
    $tx-&gt;is(
        '/html/head/link[@type="text/css"][@rel="stylesheet"]/@href',
        '/static/css/main.css',
        'Should load the CSS',
    );
}
</pre>

<p>I've set up the <code>test_basics()</code> function to test the things that should be mostly the same for every request. This will mainly cover the output of the wrapper, and includes things like making sure that there is just one <code>&lt;html&gt;</code> tag, one <code>&lt;head&gt;</code> tag, and one <code>&lt;body&gt;</code> tag; and that the title and CSS-related elements are output properly. Running this (with the test plan set to <code>no_plan</code> as I develop), I get:</p>

<pre>
% prove --lib t/view_HTML.tt
t/view_HTML.t .. 2/? 
#   Failed test 'Should load the CSS'
#   at t/view_HTML.t line 52.
#          got: ''
#     expected: '/static/css/main.css'
# Looks like you failed 1 test of 10.
t/view_HTML.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/10 subtests 

Test Summary Report
-------------------
t/view_HTML.t (Wstat: 256 Tests: 10 Failed: 1)
  Failed test:  10
  Non-zero exit status: 1
Files=1, Tests=10,  1 wallclock secs ( 0.02 usr  0.01 sys +  0.79 cusr  0.08 csys =  0.90 CPU)
Result: FAIL
</pre>

<p>Hrm. Let's stick a <code>diag $output</code> in there and see what we get. Now the output includes this bit:</p>

<pre>
# &lt;html&gt;
#  &lt;head&gt;
#   &lt;title&gt;Book List&lt;/title&gt;
#   &lt;link rel="stylesheet" href="/static/css/main.css" /&gt;
#  &lt;/head&gt;
</pre>

<p>Ah! the <code>&lt;link&gt;</code> element for the stylesheet is missing the <code>type</code> attribute. So let's add it. Edit <code>lib/MyApp/Templates/HTML.pm</code> and change the proper bit of the wrapper template to:</p>

<pre>
link {
    rel is 'stylesheet';
    type is 'text/css';
    href is $c-&gt;uri_for('/static/css/main.css' );
};
</pre>

<p>Note the addition of the <code>type</code> attribute. Now when we run the tests (removing the <code>diag</code>), we get:</p>

<pre>
% prove --lib t/view_HTML.t
t/view_HTML.t .. ok    
All tests successful.
Files=1, Tests=10,  1 wallclock secs ( 0.02 usr  0.00 sys +  0.78 cusr  0.07 csys =  0.87 CPU)
Result: PASS
</pre>

<p>Ah, much better! A lot more testing should go in there to make sure that the wrapper is doing things right. I've <a href="http://github.com/theory/catalyst-tutorial/commit/b171bfb0cb624b3a5ef840d116e121a355f5fe7d">committed</a> such testing, so check it out.</p>

<p>Now we need to test the output specific to the <code>books/list</code> template. Below the call to <code>test_bascis()</code>, add this code:</p>

<pre>
$tx-&gt;ok('/html/body/div[@id="bodyblock"]/div[@id="content"]/table', sub {
    $_-&gt;is('count(./tr)', 6, 'Should have seven rows' );
    $_-&gt;ok('./tr[1]', sub {
        $_-&gt;is('count(./th)', 3, 'Should have three table headers');
        $_-&gt;is('./th[1]', 'Title', '... first is "Title"');
        $_-&gt;is('./th[2]', 'Rating', '... second is "Rating"');
        $_-&gt;is('./th[3]', 'Authors', '... third is "Authors"');
    }, 'Should have first table row')
}, 'Should have a table');
</pre>

<p>Notice the nested block there? <a href="http://search.cpan.org/perldoc?Test::XPath" title="Test::XPath on CPAN">Test::XPath</a> supports passing blocks to its <code>ok()</code> method, so that you can naturally scope your tests to blocks of XML and HTML. Neat, huh? If you don't like the use of <code>$_</code>, the test object is also passed as the sole argument to such blocks.</p>

<p>Anyway, these tests makes sure that the table is where it should be, has the proper number of rows, and that the first row has three headers with their proper values. The test outputs:</p>

<pre>
% prove --lib t/view_HTML.tt
t/view_HTML.t .. 1/? 
#   Failed test '... third is "Authors"'
#   at t/view_HTML.t line 42.
#          got: 'Author'
#     expected: 'Authors'
# Looks like you failed 1 test of 28.
t/view_HTML.t .. Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/28 subtests 

Test Summary Report
-------------------
t/view_HTML.t (Wstat: 256 Tests: 28 Failed: 1)
  Failed test:  28
  Non-zero exit status: 1
Files=1, Tests=28,  1 wallclock secs ( 0.03 usr  0.01 sys +  0.79 cusr  0.08 csys =  0.91 CPU)
Result: FAIL
</pre>

<p>Whoops! Looks like I forgot to change the header when I changed the template to output a list of authors <a href="/computers/programming/perl/catalyst/sql-view-aggregate-magic.html" title="My Catalyst Tutorial: Add Authors to the View">last week</a>. So edit <code>lib/MyApp/Templates/HTML/Books.pm</code> and change the template to output "Authors" instead of "Author":</p>

<pre>
row {
    th { 'Title'   };
    th { 'Rating'  };
    th { 'Authors' };
};
</pre>

<p>And now all tests pass again:</p>

<pre>
% prove --lib t/view_HTML.t
t/view_HTML.t .. ok    
All tests successful.
Files=1, Tests=28,  1 wallclock secs ( 0.02 usr  0.01 sys +  0.78 cusr  0.09 csys =  0.90 CPU)
Result: PASS
</pre>

<p>Great. So let's finish testing the rest of the output. Ah, but wait! We have on <code>ORDER BY</code> clause on the query, so the order in which the books will be output is undefined. So let's add an <code>ORDER BY</code> clause. Change the creation of the statement handle in the test file to:</p>

<pre>
my $sth = $c-&gt;conn-&gt;run(sub { $_-&gt;prepare(q{
    SELECT isbn, title, rating, authors
      FROM books_with_authors
     ORDER BY title
}) });
</pre>

<p>And now you can start to see why I use the <code>q{}</code> operator for SQL queries. You should also note that the inputs for the view test are now different than those from the controller, which still has no <code>ORDER BY</code> clause. It's likely that we'll want to go back and change that later, but I bring it up here to highlight the difference from integration tests -- and to emphasize that we'll need to write those integration tests at some point!</p>

<p>But back to the view unit tests. We can now test the contents of the table by adding code after the test for <code>./tr[1]</code>. Here's what the test for the next row looks like:</p>

<pre>
$_-&gt;ok('./tr[2]', sub {
    $_-&gt;is('count(./td)', 3, 'Should have three cells');
    $_-&gt;is(
        './td[1]',
        'CCSP SNRS Exam Certification Guide',
        '... first is "CCSP SNRS Exam Certification Guide"'
    );
    $_-&gt;is('./td[2]', 5, '... second is "5"');
    $_-&gt;is(
        './td[3]',
        'Bastien, Nasseh, Degu',
        '... third is "Bastien, Nasseh, Degu"',
    );
}, 'Should have second table row');
</pre>

<p>The other rows can be similarly tested; have a look at the <a href="http://github.com/theory/catalyst-tutorial/commit/e6018bd0339fb92b9c7fe9ac3d518ca3d302f7a0">commit</a> to see all the new tests.</p>

<p>This reminds me, however, that we never created an order for the list of authors. So it's possible that this test could fail, as the order of the author last names is undefined. We should go back and fix that, probably by listing the authors as they are actually listed on the cover of the book. But in the meantime, our test of this view is done.</p>

<p>Next up, I think I'll hit controller tests. So come on back!</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/testing</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/testing.html" />
<title type="text/plain">Testing the Tutorial App</title>
<dc:subject>Catalyst</dc:subject>
<dc:subject>tutorial</dc:subject>
<dc:subject>testing</dc:subject>
<dc:subject>MVC</dc:subject>
<dc:subject>Perl</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<issued>2009-11-09T18:36:00Z</issued>
<modified>2009-11-09T18:36:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Yet another entry in my <a href="/computers/programming/perl/catalyst" title="Just a Theory: Catalyst">ongoing</a> attempt to rewrite the <a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial" title="Catalyst Tutorial: Overview">Catalyst tutorial</a> in my own coding style.</p>

<p>So far, I've been following the original tutorial pretty closely. But now I want to skip ahead a bit to <a href="Catalyst::Manual::Tutorial::08_Testing" title="Catalyst Tutorial - Chapter 8: Testing">chapter 8</a>: testing. I skip because, really, we should be writing tests from the very beginning. They shouldn&rsquo;t be an afterthought stuck in the penultimate chapter of a tutorial. So let&rsquo;s write some tests. You can follow along in the <a href="http://github.com/theory/catalyst-tutorial/commits/part-05">Part 5 tag</a> in the GitHub repository.</p>

<h3>Oops, A Missing Dependency</h3>

<p>Oh, wait! I forgot to tell the build system that we now depend on <a href="http://search.cpan.org/perldoc?Catalyst::View::TD" title="Catalyst::View::TD on CPAN">Catalyst::View::TD</a> and <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on CPAN">DBIx::Connector</a>. So add these two lines to <code>Makefile.PL</code>:</p>

<pre>
requires &#x27;Catalyst::View::TD&#x27; =&gt; &#x27;0.11&#x27;;
requires &#x27;DBIx::Connector&#x27; =&gt; &#x27;0.30&#x27;;
</pre>


<p>Okay, <em>now</em> we can write some tests.</p>

<h3>STFU</h3>

<p>Well, no, actually, let&rsquo;s start by running the tests we have:</p>

<pre>
perl Makefile.PL
make test
</pre>


<p>You should see some output after this &mdash; lots of stuff, actually &mdash; ending something like this:</p>

<pre>
[debug] Loaded Path actions:
.&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;.
| Path                                | Private                              |
+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+
| /                                   | /index                               |
| /                                   | /default                             |
| /books                              | /books/index                         |
| /books/list                         | /books/list                          |
&#x27;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x27;

[info] MyApp powered by Catalyst 5.80013
t/view_HTML.t ......... ok   
All tests successful.
Files=5, Tests=8,  3 wallclock secs ( 0.04 usr  0.02 sys +  2.19 cusr  0.25 csys =  2.50 CPU)
Result: PASS
</pre>


<p>I don&rsquo;t know about you, but having all that debugging crap just drives me nuts while I'm running tests. It&rsquo;s helpful while doing development, but mainly just gets in the way of the tests. So let&rsquo;s get rid of them. Open up <code>lib/MyApp.pm</code> and change the <code>use Catalyst</code> statement to:</p>

<pre>
use Catalyst (qw(
    ConfigLoader
    Static::Simple
    StackTrace
), $ENV{HARNESS_ACTIVE} ? () : &#x27;-Debug&#x27;);
</pre>


<p>Essentially, we're just turning on the debugging output only if the test harness is not active. Now when we run the tests, we get:</p>

<pre>
t/01app.t ............. ok   
t/02pod.t ............. skipped: set TEST_POD to enable this test
t/03podcoverage.t ..... skipped: set TEST_POD to enable this test
t/controller_Books.t .. ok   
t/view_HTML.t ......... ok   
All tests successful.
Files=5, Tests=8,  3 wallclock secs ( 0.04 usr  0.02 sys +  2.15 cusr  0.23 csys =  2.44 CPU)
Result: PASS
</pre>


<p><em>Much</em> better. Now I can actually see other stuff, such as the fact that I'm skipping POD tests. Personally, I like to make sure that POD tests run all the time, as I'm likely to forget to set the environment variable. So let&rsquo;s edit <code>t/02pod.t</code> and <code>t/03podcoverage.t</code> and delete this line from each:</p>

<pre>
plan skip_all =&gt; &#x27;set TEST_POD to enable this test&#x27; unless $ENV{TEST_POD};
</pre>


<p>So what does that get us?</p>

<pre>
t/01app.t ............. ok   
t/02pod.t ............. ok     
t/03podcoverage.t ..... 1/6 
#   Failed test &#x27;Pod coverage on MyApp::Controller::Books&#x27;
#   at /usr/local/lib/perl5/site_perl/5.10.1/Test/Pod/Coverage.pm line 126.
# Coverage for MyApp::Controller::Books is 50.0%, with 1 naked subroutine:
#   list

#   Failed test &#x27;Pod coverage on MyApp::Controller::Root&#x27;
#   at /usr/local/lib/perl5/site_perl/5.10.1/Test/Pod/Coverage.pm line 126.
# Coverage for MyApp::Controller::Root is 66.7%, with 1 naked subroutine:
#   default
# Looks like you failed 2 tests of 6.
t/03podcoverage.t ..... Dubious, test returned 2 (wstat 512, 0x200)
Failed 2/6 subtests 
t/controller_Books.t .. ok   
t/view_HTML.t ......... ok   

Test Summary Report
&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;
t/03podcoverage.t   (Wstat: 512 Tests: 6 Failed: 2)
  Failed tests:  2&#x2d;3
  Non&#x2d;zero exit status: 2
Files=5, Tests=25,  3 wallclock secs ( 0.05 usr  0.02 sys +  2.82 cusr  0.29 csys =  3.18 CPU)
Result: FAIL
Failed 1/5 test programs. 2/25 subtests failed.
</pre>


<p>Well that figures, doesn&rsquo;t it? We added the <code>list</code> action to  MyApp::Controller Books but never documented it. And for some reason, Catalyst creates the <code>default</code> action in MyApp::Controller::Root with no documentation. Such a shame. So let&rsquo;s document those methods. Add this to <code>t/lib/MyApp/Controller/Root.pm</code>:</p>

<pre>
=head2 default

The default action. Just returns a 404/NOT FOUND error. Might want to update
later with a template to format the error like the rest of our site.

=cut
</pre>


<p>While there, I notice that the <code>index</code> action has a doc header, but nothing to actually describe what it does. Let&rsquo;s fix that, too:</p>

<pre>
The default Catalyst action, which just displays the welcome message. This is
the &quot;Yay it worked!&quot; page. Consider changing to a real home page for our app.
</pre>


<p>Great. Now open <code>t/lib/MyApp/Controller/Books.pm</code> and document the <code>list</code> action:</p>

<pre>
=head2 list

Looks up all of the books in the system and executes a template to display
them in a nice table. The data includes the title, rating, and authors of each
book

=cut
</pre>


<p>Oh hey, look at that. There&rsquo;s an <code>index</code> method that doesn&rsquo;t do anything. And it has a POD header and no docs, too. So let&rsquo;s document it:</p>

<pre>
The default method for the books controller. Currently just says that it
matches the request; we&#x27;ll likely want to change it to something more
reasonable down the line.
</pre>


<p>Okay, so how do the tests look now?</p>

<pre>
t/01app.t ............. ok   
t/02pod.t ............. ok     
t/03podcoverage.t ..... ok   
t/controller_Books.t .. ok   
t/view_HTML.t ......... ok   
All tests successful.
Files=5, Tests=25,  3 wallclock secs ( 0.05 usr  0.02 sys +  2.82 cusr  0.31 csys =  3.20 CPU)
Result: PASS
</pre>


<p>Excellent! Now, the truth is that we didn&rsquo;t document our templates, either. Test::Pod doesn&rsquo;t cotton on to that fact because they're not installed like normal subroutines in the test classes. So it&rsquo;s up to us to document them ourselves. (Note to self: Consider adding a module to test that all Template::Declare classes have docs for all of their templates.) I'll wait here while you do that.</p>

<p>All done? Great! I had actually planned to start testing the view next, but I think this is enough for today. Stay tuned for more testing goodness.</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/tutorial-on-git</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/tutorial-on-git.html" />
<title type="text/plain">Tutorial on GitHub</title>
<dc:subject>Perl</dc:subject>
<dc:subject>Catalyst</dc:subject>
<dc:subject>git</dc:subject>
<dc:subject>GitHub</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>DBIx::Connector</dc:subject>
<dc:subject>tutorial</dc:subject>
<issued>2009-11-06T18:58:00Z</issued>
<modified>2009-11-06T18:58:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Following a very good <a href="/computers/programming/perl/catalyst/sql-view-aggregate-magic.html#tb" title="My Catalyst Tutorial: Add Authors to the View—Comments">suggestion from Pedro Melo</a>, I've created a Git repository for this tutorial and put it <a href="http://github.com/theory/catalyst-tutorial" title="Catalyst Tutorial on GitHub">on GitHub</a>. I replayed each step, making each into its own <a href="http://github.com/theory/catalyst-tutorial/commits/master" title="Commit History for Catalyst Tutorial">commit</a>, and tagged the state of the code for each entry:</p>

<ul>
<li><a href="http://github.com/theory/catalyst-tutorial/commits/part-01">Create Catalyst Views with Template::Declare</a></li>
<li><a href="http://github.com/theory/catalyst-tutorial/commits/part-02">Catalyst with DBIx::Connector and Template::Declare</a></li>
<li><a href="http://github.com/theory/catalyst-tutorial/commits/part-03">Create a Template::Declare Wrapper</a></li>
<li><a href="http://github.com/theory/catalyst-tutorial/commits/part-04">My Catalyst Tutorial: Add Authors to the View</a></li>
</ul>


<p>So as I continue to make modifications, I'll keep this repository up-to-date, and tag things as of each blog entry. This will make it easy for you to follow along; you can simply clone <a href="git://github.com/theory/catalyst-tutorial.git">the repository</a> and <code>git pull</code> for each post.</p>

<p>More soon.</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/sql-view-aggregate-magic</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/sql-view-aggregate-magic.html" />
<title type="text/plain">My Catalyst Tutorial: Add Authors to the View</title>
<dc:subject>Catalyst</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>database</dc:subject>
<dc:subject>DBI</dc:subject>
<dc:subject>PostgreSQL</dc:subject>
<dc:subject>SQL</dc:subject>
<dc:subject>aggregate</dc:subject>
<issued>2009-11-05T14:00:00Z</issued>
<modified>2009-11-05T14:00:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Another post in my ongoing <a href="/computers/programming/perl/catalyst%20title=" title="Just a Theory: “Catalyst”">series</a> of posts on using Catalyst with Template::Declare and DBIx::Connector. This will be the last post covering material from <a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics" title="Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics">chapter 3</a>, I promise. This is a fun one, though, because we continue to use this really nice <a href="http://en.wikipedia.org/wiki/Domain-specific_language" title="Wikipedia: “Domain-Specific Language”">DSL</a> called &ldquo;SQL,&rdquo; which I think is more expressive than an ORM would be.</p>

<p>To whit, the next task is to add the missing list of authors to the book list. The thing is, the more I work with databases, the more I'm inclined to think about them not only as the &ldquo;M&rdquo; in &ldquo;<a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" title="Wikipedia: “Model-view-controller”">MVC</a>&rdquo;, but also the &ldquo;V&rdquo;. I'll show you what I mean.</p>

<h3>A Quick Fix</h3>

<p>But first, a diversion. In the <a href="/computers/programming/perl/catalyst/tutorial-continued.html">second post</a> in this series, I created an SQL statement to insert book authors, but I made a mistake: the values for surnames and given names were reversed. Oops. Furthermore, I included explicit author IDs, even though the <code>id</code> column uses a sequence for it&rsquo;s default value. So first we need to fix these issues. Change  the <code>INSERT INTO authors</code> statement in <code>sql/001-books.sql</code> to:</p>

<pre>
INSERT INTO authors (surname, given_name)
VALUES (&#x27;Bastien&#x27;,      &#x27;Greg&#x27;),
       (&#x27;Nasseh&#x27;,       &#x27;Sara&#x27;),
       (&#x27;Degu&#x27;,         &#x27;Christian&#x27;),
       (&#x27;Stevens&#x27;,      &#x27;Richard&#x27;),
       (&#x27;Comer&#x27;,        &#x27;Douglas&#x27;),
       (&#x27;Christiansen&#x27;, &#x27;Tom&#x27;),
       (&#x27;Torkington&#x27;,   &#x27;Nathan&#x27;),
       (&#x27;Zeldman&#x27;,      &#x27;Jeffrey&#x27;)
;
</pre>


<p>This time, we're letting the sequence populate the <code>id</code> column. Fortunately, it starts from 1 just like we did, so we don&rsquo;t need to update the values in the <code>INSERT INTO book_author</code> statement. Now let&rsquo;s fix the database:</p>

<pre><code>DELETE FROM book_author;
DELETE FROM authors;
</code></pre>

<p>Then run the above SQL query to restore the authors with their proper names, and then run the <code>INSERT INTO book_author</code> statement. That will get us back in business.</p>

<h3>Constructing our Query</h3>

<p>Now it&rsquo;s time for the fun. The original SQL query we wrote to get the list of books was:</p>

<pre><code>SELECT isbn, title, rating FROM books;
</code></pre>

<p>Nothing unusual there. But to get at the authors, we need to join to <code>book_author</code> and from there to <code>authors</code>. Our first cut looks like this:</p>

<pre><code>SELECT b.isbn, b.title, b.rating, a.surname
  FROM books       b
  JOIN book_author ba ON b.isbn       = ba.isbn
  JOIN authors     a  ON ba.author_id = a.id;
</code></pre>

<p>Which yields this data:</p>

<pre>
       isbn        |               title                | rating |   surname    
&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;
 978&#x2d;1&#x2d;58720&#x2d;153&#x2d;0 | CCSP SNRS Exam Certification Guide |      5 | Bastien
 978&#x2d;1&#x2d;58720&#x2d;153&#x2d;0 | CCSP SNRS Exam Certification Guide |      5 | Nasseh
 978&#x2d;1&#x2d;58720&#x2d;153&#x2d;0 | CCSP SNRS Exam Certification Guide |      5 | Degu
 978&#x2d;0&#x2d;201&#x2d;63346&#x2d;7 | TCP/IP Illustrated, Volume 1       |      5 | Stevens
 978&#x2d;0&#x2d;13&#x2d;018380&#x2d;4 | Internetworking with TCP/IP Vol.1  |      4 | Comer
 978&#x2d;1&#x2d;56592&#x2d;243&#x2d;3 | Perl Cookbook                      |      5 | Christiansen
 978&#x2d;1&#x2d;56592&#x2d;243&#x2d;3 | Perl Cookbook                      |      5 | Torkington
 978&#x2d;0&#x2d;7357&#x2d;1201&#x2d;0 | Designing with Web Standards       |      5 | Zeldman
</pre>


<p>Good start, but note how we now have three rows for “CCSP SNRS Exam Certification Guide” and two for “Perl Cookbook”. We could of course modify our Perl code to look at the ISBN in each row and combine as appropriate, but it&rsquo;s better to get the database to do that work, since it&rsquo;s designed for that sort of thing. So let&rsquo;s use an <a href="http://www.postgresql.org/docs/current/static/functions-aggregate.html" title="PostgreSQL Documentation: “Aggregate Functions”">aggregate function</a> to combine the values over multiple rows into a single row. All we have to do is use the column that changes (<code>surname</code>) in an aggregate function and tell PostgreSQL to use the other columns to group rows into one. PostgreSQL 8.4 introduces a really nice aggregate function, <code>array_agg()</code>, for pulling a series of strings together into an array. Let&rsquo;s put it to use:</p>

<pre><code>SELECT b.isbn, b.title, b.rating, array_agg(a.surname) as authors
  FROM books       b
  JOIN book_author ba ON b.isbn     = ba.isbn
  JOIN authors     a  ON ba.author_id = a.id
 GROUP BY b.isbn, b.title, b.rating;
</code></pre>

<p>Now the output is:</p>

<pre>
       isbn        |               title                | rating |          authors         
&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;
 978&#x2d;0&#x2d;201&#x2d;63346&#x2d;7 | TCP/IP Illustrated, Volume 1       |      5 | {Stevens}
 978&#x2d;0&#x2d;13&#x2d;018380&#x2d;4 | Internetworking with TCP/IP Vol.1  |      4 | {Comer}
 978&#x2d;1&#x2d;56592&#x2d;243&#x2d;3 | Perl Cookbook                      |      5 | {Christiansen,Torkington}
 978&#x2d;1&#x2d;58720&#x2d;153&#x2d;0 | CCSP SNRS Exam Certification Guide |      5 | {Bastien,Nasseh,Degu}
 978&#x2d;0&#x2d;7357&#x2d;1201&#x2d;0 | Designing with Web Standards       |      5 | {Zeldman}
</pre>


<p>Much better. We now have a single row for each book, and the authors are all grouped into a single column. Cool. But we can go one step further. Although we could use Perl to turn the array of author surnames into a comma-delimited string, there&rsquo;s a PostgreSQL function for that, too: <code>array_to_string()</code>. Check it out:</p>

<pre><code>SELECT b.isbn, b.title, b.rating,
       array_to_string(array_agg(a.surname), ', ') as authors
  FROM books       b
  JOIN book_author ba ON b.isbn     = ba.isbn
  JOIN authors     a  ON ba.author_id = a.id
 GROUP BY b.isbn, b.title, b.rating;
</code></pre>

<p>Now the rows will be:</p>

<pre>
       isbn        |               title                | rating |          authors          
&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;
 978&#x2d;0&#x2d;201&#x2d;63346&#x2d;7 | TCP/IP Illustrated, Volume 1       |      5 | Stevens
 978&#x2d;0&#x2d;13&#x2d;018380&#x2d;4 | Internetworking with TCP/IP Vol.1  |      4 | Comer
 978&#x2d;1&#x2d;56592&#x2d;243&#x2d;3 | Perl Cookbook                      |      5 | Christiansen, Torkington
 978&#x2d;1&#x2d;58720&#x2d;153&#x2d;0 | CCSP SNRS Exam Certification Guide |      5 | Bastien, Nasseh, Degu
 978&#x2d;0&#x2d;7357&#x2d;1201&#x2d;0 | Designing with Web Standards       |      5 | Zeldman
</pre>


<h3>Create a Database View</h3>

<p>Cool! All the formatting work is done! But since it&rsquo;s likely what we'll often need to fetch book titles along with their authors, let&rsquo;s create an SQL view for this query. That way, we don&rsquo;t have to write the same SQL in different places in the application: we can just use the view. So create a new file, <code>sql/002-books_with_authors.sql</code>, and add this SQL:</p>

<pre><code>CREATE VIEW books_with_authors AS
SELECT b.isbn, b.title, b.rating,
       array_to_string(array_agg(a.surname), ', ') as authors
  FROM books       b
  JOIN book_author ba ON b.isbn     = ba.isbn
  JOIN authors     a  ON ba.author_id = a.id
 GROUP BY b.isbn, b.title, b.rating;
</code></pre>

<p>Now install this view in the database:</p>

<pre><code>psql -U postgres -d myapp -f sql/002-books_with_authors.sql
</code></pre>

<p>And now we can make use of the view any time we want and get the results of the full query. It&rsquo;s time to do that in our controller. Edit <code>lib/MyApp/Controller/Books.pm</code> and change this line  in the <code>list</code> action:</p>

<pre><code>my $sth = $_-&gt;prepare('SELECT isbn, title, rating FROM books');
</code></pre>

<p>To:</p>

<pre><code>my $sth = $_-&gt;prepare(q{
    SELECT isbn, title, rating, authors FROM books_with_authors
});
</code></pre>

<p>The use of the <code>q{}</code> operator is a style I use for SQL queries in Perl code; you can use whatever style you like. Since this is a very short SQL statement (thanks to the view), it&rsquo;s not really necessary to have it on multiple lines, but I like to be fairly consistent about this sort of thing.</p>

<p>The last thing we need to do is a a very simple change to the <code>list</code> template in <code>lib/MyApp/Templates/HTML/Books.pm</code>. In previous posts, I was referring to the non-existent &ldquo;author&rdquo; key in the each hash reference fetched from the database. In the new view, however, I've named that column &ldquo;authors&rdquo;. So change this line:</p>

<pre><code>cell { $book-&gt;{author} };
</code></pre>

<p>To</p>

<pre><code>cell { $book-&gt;{authors} };
</code></pre>

<p>And that&rsquo;s it. Restart the server and reload <code>http://localhost:3000/books/list</code> and you should now see all of the books listed with their authors.</p>

<h3>Notes</h3>

<p>I think you can appreciate why, to a certain degree, I'm starting to think of the database as handling both the &ldquo;M&rdquo; and the &ldquo;V&rdquo; in &ldquo;MVC&rdquo;. It&rsquo;s no mistake that the database object we created is known as a &ldquo;view&rdquo;. It was written in such a way that it not only expressed the relationship between books and authors in a compact but clear way, but it formatted the appropriate data for publishing on the site&mdash;all in a single, efficient query. All the Template::Declare view does is wrap it all up in the appropriate HTML.</p>

<p>PostgreSQL isn&rsquo;t the only database to support feature such as this, by the way. All of the databases I've used support views, and many offer useful aggregate functions, as well. Among the <a href="http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html" title="MySQL Documentation: “GROUP BY (Aggregate) Functions”">MySQL aggregates</a>, for example, is <code>group_concat()</code>, which sort of combines the <code>array_to_string(array_agg())</code> PostgreSQL syntax into a single function. And I've <a href="http://www.justatheory.com/computers/databases/sqlite/custom_perl_aggregates.html" title="Just a Theory: “Custom Aggregates in Perl”">personally written</a> a custom aggregate for SQLite in Perl. So although I use PostgreSQL for these examples and make use of its functionality, you can do much the same thing in most other databases.</p>

<p>Either way, I find this to be a lot less work than using an ORM or other abstraction layer between my app and the database. Frankly, SQL provides just the right level of abstraction.</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/databases/postgresql/pgtap-best-practices</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/databases/postgresql/pgtap-best-practices.html" />
<title type="text/plain">pgTAP Best Practices Slides Available</title>
<dc:subject>TAP</dc:subject>
<dc:subject>pgTAP</dc:subject>
<dc:subject>testing</dc:subject>
<dc:subject>unit</dc:subject>
<dc:subject>testing</dc:subject>
<dc:subject>database</dc:subject>
<dc:subject>SQL</dc:subject>
<dc:subject>plpgSQL</dc:subject>
<dc:subject>PostgreSQL</dc:subject>
<issued>2009-11-04T20:13:00Z</issued>
<modified>2009-11-04T20:13:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><div style="width:425px;text-align:left" class="left" id="__ss_2423179"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/justatheory/pgtap-best-practices" title="PgTAP Best Practices">PgTAP Best Practices</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=pgtapbestpractices-091104135201-phpapp01&amp;stripped_title=pgtap-best-practices" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=pgtapbestpractices-091104135201-phpapp01&amp;stripped_title=pgtap-best-practices" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355" /></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/justatheory">David Wheeler</a>.</div></div>

<p>Last month I gave two presentations at the <a href="http://www.postgresqlconference.org/2009/west/" title="West 2009, Seattle! | PostgreSQL Conference">PostgreSQL Conference West</a>. The first was a variation on <a href="/computers/databases/postgresql/unit-test-your-database.html" title="Just a Theory: “Unit Test Your Database!”">Unit Test Your Database!</a>, which I've now given about six times (and will at least two more times, including tomorrow night for <a href="http://www.pdxlinux.org/" title="Portland Linux/Unix User Group">Portland PLUG</a> and in two weeks at the <a href="http://www.postgresql.jp/events/pgcon09j/e/">JPUG 10th Anniversary Conference</a>). The second was a new talk, a 90-minute tutorial, called “pgTAP Best Practices.” And here it is, published on Slideshare. Enjoy.</p>

<p>You can also download a 76MB <a href="http://www.kineticode.com/docs/pgtap_best_practices.pdf" title="pgTAP Best Practices">PDF</a> if that's more your style.</p>

<p>Enjoy!</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/template-declare-wrapper</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/template-declare-wrapper.html" />
<title type="text/plain">Create a Template::Declare Wrapper</title>
<dc:subject>Catalyst</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>Perl</dc:subject>
<dc:subject>wrapper</dc:subject>
<dc:subject>MVC</dc:subject>
<dc:subject>Template+Toolkit</dc:subject>
<issued>2009-11-04T14:00:00Z</issued>
<modified>2009-11-04T14:00:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Next in my ongoing <a href="/computers/programming/perl/catalyst%20title=" title="Just a Theory: “Catalyst”">series</a> of posts on using Catalyst with Template::Declare and DBIx::Connector, we pick up again in chapter 3 to <a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics#CREATE_A_WRAPPER_FOR_THE_VIEW" title="Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics">create a wrapper for the view</a>. I added the wrapper support to <a href="http://search.cpan.org/perldoc?Template::Declare" title="Template::Declare on CPAN">Template::Declare</a> over a year ago, and while the idea is sound, the interface makes it feel like it&rsquo;s bolted on. See if you agree with me.</p>

<p>Returning to the MyApp project, open <code>lib/MyApp/Templates/HTML.pm</code> and implement a wrapper like so:</p>

<pre>
use Sub::Exporter -setup => { exports => [qw(wrapper) ] };

create_wrapper wrapper => sub {
    my ($code, $c, $args) = @_;
    xml_decl { &#x27;xml&#x27;, version =&gt; &#x27;1.0&#x27; };
    outs_raw &#x27;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &#x27;
           . &#x27;&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;&#x27;;
    html {
        head {
            title { $args-&gt;{title} || &#x27;My Catalyst App!&#x27; };
            link {
                rel is &#x27;stylesheet&#x27;;
                href is $c-&gt;uri_for(&#x27;/static/css/main.css&#x27; );
            };

        };

        body {
            div {
                id is &#x27;header&#x27;;
                # Your logo can go here.
                img {
                    src is $c-&gt;uri_for(&#x27;/static/images/btn_88x31_powered.png&#x27;);
                };
                # Page title.
                h1 { $args-&gt;{title} || $c-&gt;config-&gt;{name} };
            }; # end header.

            div {
                id is &#x27;bodyblock&#x27;;
                div {
                    id is &#x27;menu&#x27;;
                    h3 { &#x27;Navigation&#x27; };
                    ul {
                        li {
                            a {
                                href is $c-&gt;uri_for(&#x27;/books/list&#x27;);
                                &#x27;Home&#x27;;
                            };
                        };
                        li {
                            a {
                                href is $c-&gt;uri_for(&#x27;/&#x27;);
                                title is &#x27;Catalyst Welcome Page&#x27;;
                                &#x27;Welcome&#x27;;
                            };
                        };
                    };
                }; # end menu

                div {
                    id is &#x27;content&#x27;;
                    # Status and error messages.
                    if (my $msg = $args-&gt;{status_msg}) {
                        span { class is &#x27;message&#x27;; $msg };
                    }
                    if (my $err = $args-&gt;{error_msg}) {
                        span { class is &#x27;error&#x27;; $err };
                    }

                    # Output the template contents.
                    $code-&gt;($args);
                }; # end content

            }; # end bodyblock
        };
    };
};
</pre>


<p>This looks like more work than it is because of the copious use of whitespace I've used. Personally, I find the pure Perl syntax easier to read than the mix of HTML and TT syntax in the Template Toolkit wrapper. Anyway, this is a nearly direct port of the Template Toolkit wrapper from the tutorial. Template::Declare wrappers expect at least one argument: a code reference that will output the content of the main template. You can see it used here near the end of the code, with the line <code>$code-&gt;($args)</code>.</p>

<p>Unfortunately, Template::Declare doesn&rsquo;t make such wrappers easily available to templates. So we have to add the <code>Sub::Exporter</code> line at the top to export the wrapper function it creates, named <code>wrapper</code>.</p>

<p>Next, open up <code>lib/MyApp/Templates/HTML/Books.pm</code>  and edit the <code>list</code> template to take advantage of the wrapper. The new code looks like this:</p>

<pre>
use MyApp::Templates::HTML &#x27;wrapper&#x27;;

template list =&gt; sub {
    my ($self, $args) = @_;
    wrapper {
        table {
            row {
                th { &#x27;Title&#x27;  };
                th { &#x27;Rating&#x27; };
                th { &#x27;Author&#x27; };
            };
            my $sth = $args-&gt;{books};
            while (my $book = $sth-&gt;fetchrow_hashref) {
                row {
                    cell { $book-&gt;{title}  };
                    cell { $book-&gt;{rating} };
                    cell { $book-&gt;{author} };
                };
            };
        };
    } $self-&gt;c, $args;
};
</pre>


<p>First we import the <code>wrapper</code> function from MyApp::Templates::HTML, and then we simply use it to wrap the contents of our template. Note that the context object and template arguments must be passed on to the wrapper; they're not provided to the wrapper by Template::Declare. That&rsquo;s something else I'd like to adjust.</p>

<p>In the meantime, contrary to the tutorial, I don&rsquo;t think the template should set the title of the page. It seems to me that&rsquo;s more the responsibility of the controller. So while this template could easily add a <code>title</code> key to the <code>$args</code> hash before passing it on to the wrapper, I recommend editing the <code>list</code> action in MyApp::Controller::Books instead:</p>

<pre>
sub list : Local {
    my ($self, $c) = @_;
    my $stash = $c-&gt;stash;
    $stash-&gt;{title} = &#x27;Book List&#x27;;
    $stash-&gt;{books} = $c-&gt;conn-&gt;run(fixup =&gt; sub {
        my $sth = $_-&gt;prepare(&#x27;SELECT isbn, title, rating FROM books&#x27;);
        $sth-&gt;execute;
        $sth;
    });
}
</pre>


<p>So, with the wrapper in place, let&rsquo;s create the stylesheet the wrapper uses:</p>

<pre>
$ mkdir root/static/css
</pre>


<p>Then open <code>root/static/css/main.css</code> and add the following content:</p>

<pre>
#header {
  text-align: center;
}
#header h1 {
  margin: 0;
}
#header img {
  float: right;
}
#footer {
  text-align: center;
  font-style: italic;
  padding-top: 20px;
}
#menu {
  font-weight: bold;
  background-color: #ddd;
  float: left;
  padding: 0 0 50% 5px;
}
#menu ul {
  margin: 0;
  padding: 0;
  list-style: none;
  font-weight: normal;
  background-color: #ddd;
  width: 100px;
}
#content {
  margin-left: 120px;
}
.message {
  color: #390;
}
.error {
  color: #f00;
}
</pre>


<p>Now restart the app as usual and reload the books list at <code>http://localhost:3000/books/list</code>. You should now see a nicely formatted page with the navigation and header stuff, as well as the book list. You can  change the CSS and the wrapper to modify the overall look of your site, and then use the wrapper in all of your page request templates to get the same look and feel across your site.</p>

<p>While this works, I'm not satisfied with the overall interface for Template::Declare wrappers. The need to explicitly export them and pass arguments is annoying. Maybe the <a href="http://jifty.org/">Jifty</a> guys have some other approach that works better. But if not, I'll likely go back to the drawing board on wrappers and see how they can be made better.</p>

<p>Next up: More database fun!</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/tutorial-continued</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/tutorial-continued.html" />
<title type="text/plain">Catalyst with DBIx::Connector and Template::Declare</title>
<dc:subject>Perl</dc:subject>
<dc:subject>Catalyst</dc:subject>
<dc:subject>DBIx::Connector</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>PostgreSQL</dc:subject>
<issued>2009-11-03T14:00:00Z</issued>
<modified>2009-11-03T14:00:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Following up on my <a href="/computers/programming/perl/catalyst/catalyst-view-td.html" title="Create Catalyst Views with Template::Declare">post</a> yesterday introducing <a href="http://search.cpan.org/perldoc?Catalyst::View::TD" title="Calyst::View::TD on CPAN">Catalyst::View::TD</a>, today I'd like to continue with the next step in <a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics" title="Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics">chapter 3</a> of the Catalyst tutorial. The twist here is that I'm going to use <a href="http://www.postgresql.org/" title="PostgreSQL: The world's most advanced open source database">PostgreSQL</a> for the database back-end and start introducing some database best practices. I'm also going to make use of my <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on CPAN">DBIx::Connector</a> module to interact with the database.</p>

<h3>Create the Database</h3>

<p>Picking up with the <a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics#CREATE_A_SQLITE_DATABASE" title="Create a SQLite Database">database creation</a> section of the tutorial, the first change I'd like to make is to use a <a href="http://en.wikipedia.org/wiki/Natural_key" title="Wikipedia: “Natural Key”">natural key</a> for the books table. All books have unique identifiers, known as ISBNs, so creating a <a href="http://en.wikipedia.org/wiki/Surrogate_key" title="Wikipedia: “Surrogate Key”">surrogate key</a> (the typical <code>id</code> column in ORM-managed applications) is redundant. One of the nice things about PostgreSQL is that it ships with a contributed library, <a href="http://www.postgresql.org/docs/current/static/isn.html" title="PostgreSQL Documentation: “isn”">isn</a>, which validates ISBN and other international identifiers. So we use this contrib module (usually included in package-installed PostgreSQL servers) for the primary key for books. If you need to install it from source, it&rsquo;s pretty easy:</p>

<pre>
cd postgresql-8.4.1/contrib/isn
make
make install
</pre>


<p>Ideally I'd use a natural key for the authors table too, but despite <a href="http://dlist.sir.arizona.edu/1716/" title="The Universal Author Identifier System (UAI_Sys)">some attempts</a> to create universal identifiers for authors, nothing has really caught on as far as I know. So I'll just stick to a surrogate key for now.</p>

<p>First step: create the database and install isn if it&rsquo;s not already included in the template database:</p>

<pre>
createdb -U postgres myapp
psql -U postgres -d myapp -f /usr/local/pgsql/share/contrib/isn.sql
</pre>


<p>The <code>isn.sql</code> file may be somewhere else on your system. Now let&rsquo;s create the database. Create <code>sql/001-books.sql</code> in the <code>MyApp</code> directory and paste this into it:</p>

<pre>
BEGIN;

CREATE TABLE books (
    isbn   ISBN13   PRIMARY KEY,
    title  TEXT     NOT NULL DEFAULT &#x27;&#x27;,
    rating SMALLINT NOT NULL DEFAULT 0 CHECK (rating BETWEEN 0 AND 5)
);

CREATE TABLE authors (
    id         BIGSERIAL PRIMARY KEY,
    surname    TEXT NOT NULL DEFAULT &#x27;&#x27;,
    given_name TEXT NOT NULL DEFAULT &#x27;&#x27;
);

CREATE TABLE book_author (
    isbn       ISBN13 REFERENCES books(isbn),
    author_id  BIGINT REFERENCES authors(id),
    PRIMARY KEY (isbn, author_id)
);

INSERT INTO books
VALUES (&#x27;1587201534&#x27;,        &#x27;CCSP SNRS Exam Certification Guide&#x27;, 5),
       (&#x27;978-0201633467&#x27;,    &#x27;TCP/IP Illustrated, Volume 1&#x27;,       5),
       (&#x27;978-0130183804&#x27;,    &#x27;Internetworking with TCP/IP Vol.1&#x27;,  4),
       (&#x27;978-1-56592-243-3&#x27;, &#x27;Perl Cookbook&#x27;,                      5),
       (&#x27;978-0735712010&#x27;,    &#x27;Designing with Web Standards&#x27;,       5)
;

INSERT INTO authors
VALUES (1, &#x27;Greg&#x27;,      &#x27;Bastien&#x27;),
       (2, &#x27;Sara&#x27;,      &#x27;Nasseh&#x27;),
       (3, &#x27;Christian&#x27;, &#x27;Degu&#x27;),
       (4, &#x27;Richard&#x27;,   &#x27;Stevens&#x27;),
       (5, &#x27;Douglas&#x27;,   &#x27;Comer&#x27;),
       (6, &#x27;Tom&#x27;,       &#x27;Christiansen&#x27;),
       (7, &#x27;Nathan&#x27;,    &#x27;Torkington&#x27;),
       (8, &#x27;Jeffrey&#x27;,   &#x27;Zeldman&#x27;)
;

INSERT INTO book_author
VALUES (&#x27;1587201534&#x27;,        1),
       (&#x27;1587201534&#x27;,        2),
       (&#x27;1587201534&#x27;,        3),
       (&#x27;978-0201633467&#x27;,    4),
       (&#x27;978-0130183804&#x27;,    5),
       (&#x27;978-1-56592-243-3&#x27;, 6),
       (&#x27;978-1-56592-243-3&#x27;, 7),
       (&#x27;978-0735712010&#x27;,    8)
;

COMMIT;
</pre>


<p>Yeah, I Googled for the ISBNs for those books. I found the ISBN-13 number for most of them, but it handles the old ISBN-10 format, too, automatically upgrading it to ISBN-13. I also added a <code>CHECK</code> constraint for the <code>rating</code> column, to be sure that the value is always <code>BETWEEN 0 AND 5</code>. I also like to include default values where it&rsquo;s sensible to do so, and that syntax for inserting multiple rows at once is pretty nice to have.</p>

<p>Go ahead and run this against your database:</p>

<pre><code>psql -U postgres -d myapp -f sql/001-books.sql
</code></pre>

<p>Now if you connect to the server, you should be able to query things like so:</p>

<pre>
$ psql -U postgres myapp
psql (8.4.1)
Type &quot;help&quot; for help.

myapp=# select * from books;
       isbn        |               title                | rating 
&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;+&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;&#x2d;
 978-1-58720-153-0 | CCSP SNRS Exam Certification Guide |      5
 978-0-201-63346-7 | TCP/IP Illustrated, Volume 1       |      5
 978-0-13-018380-4 | Internetworking with TCP/IP Vol.1  |      4
 978-1-56592-243-3 | Perl Cookbook                      |      5
 978-0-7357-1201-0 | Designing with Web Standards       |      5
(5 rows)
</pre>


<h3>Setup the Database Connection</h3>

<p>Great! The database is set. Now we need a way for the app to talk to it. I've not yet decided how I'm going to integrate <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on CPAN">DBIx::Connector</a> into a Catalyst model class; maybe I'll figure it out as I write these posts. But since my mantra is “the database <em>is</em> the model,” for now I won&rsquo;t bother with a model at all. Instead, I'll create a simple accessor in <code>MyApp</code> so we can easily get at the database connection wherever we need it. To do that, add these lines to <code>lib/MyApp.pm</code>:</p>

<pre>
use Moose;
use DBIx::Connector;
use Exception::Class::DBI;

has conn =&gt; (is =&gt; &#x27;ro&#x27;, lazy =&gt; 1, default =&gt; sub {
    DBIx::Connector-&gt;new( &#x27;dbi:Pg:dbname=myapp&#x27;, &#x27;postgres&#x27;, &#x27;&#x27;, {
        PrintError     =&gt; 0,
        RaiseError     =&gt; 0,
        HandleError    =&gt; Exception::Class::DBI-&gt;handler,
        AutoCommit     =&gt; 1,
        pg_enable_utf8 =&gt; 1,
    });
});
</pre>


<p>We load <a href="http://search.cpan.org/perldoc?Moose" title="Moose on CPAN">Moose</a> to get the <code>has</code> keyword, the officially sanctioned interface for defining attributes in Catalyst classes. Then I use that keyword to create the <code>conn</code> attribute. This attribute is read-only and has a DBIx::Connector object for its default value. The nice thing about this is that the DBIx::Connector object won&rsquo;t be instantiated until it&rsquo;s actually needed, and then it will be kept forever. We never have to do anything else to use it.</p>

<p>Oh, and I like to make sure that text data coming back from PostgreSQL is properly encoded as UTF-8, and I like to use <a href="http://search.cpan.org/perldoc?Exception::Class::DBI" title="Exception::Class::DBI on CPAN">Exception::Class::DBI</a> to turn DBI errors into exception objects.</p>

<p>Now it&rsquo;s time to update our controller and template to fetch actual data from the database. Edit <code>lib/MyApp/Controller/Books.pm</code> and change the <code>list</code> method to:</p>

<pre>
sub list : Local {
    my ($self, $c) = @_;
    $c-&gt;stash-&gt;{books} = $c-&gt;conn-&gt;run(fixup =&gt; sub {
        my $sth = $_-&gt;prepare(&#x27;SELECT isbn, title, rating FROM books&#x27;);
        $sth-&gt;execute;
        $sth;
    });
}
</pre>


<p>All we're doing here is creating a statement handle for the query, executing the query, and storing the statement handle in the stash. Now we need to update the template to use the statement handle. Open up <code>lib/MyApp/Templates/HTML/Books.pm</code> and change the <code>list</code> template to:</p>

<pre>
template list =&gt; sub {
    my ($self, $args) = @_;
    table {
        row {
            th { &#x27;Title&#x27;  };
            th { &#x27;Rating&#x27; };
            th { &#x27;Author&#x27; };
        };
        my $sth = $args-&gt;{books};
        while (my $book = $sth-&gt;fetchrow_hashref) {
            row {
                cell { $book-&gt;{title}  };
                cell { $book-&gt;{rating} };
                cell { $book-&gt;{author} };
            };
        };
    };
};
</pre>


<p>All we do is fetch each row from the statement handle and output it. The only thing that&rsquo;s changed is the use of the statement handle as an iterator rather than an array reference.</p>

<p>And now we're set! Restart your server with <code>script/myapp_server.pl</code> and point your browser at <code>http://localhost:3000/books/list</code>. Now you should see the book titles and ratings, though the authors still aren&rsquo;t present. We'll fix that in a later post.</p>

<h3>Takeaway</h3>

<p>The takeaway from this post: Use PostgreSQL&rsquo;s support for custom data types to create validated natural keys for your data, and use a stable, persistent database connection to talk directly to the database. No need for an ORM here, as the <a href="http://search.cpan.org/perldoc?DBI" title="The DBI on CPAN">DBI</a> provides a very Perlish access to a very capable <a href="http://en.wikipedia.org/wiki/Domain-specific_language" title="Wikipedia: “Domain-Specific Language”">DSL</a> for models called SQL.</p>

<p>More soon.</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/catalyst/catalyst-view-td</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/catalyst/catalyst-view-td.html" />
<title type="text/plain">Create Catalyst Views with Template::Declare</title>
<dc:subject>Perl</dc:subject>
<dc:subject>Catalyst</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>templates</dc:subject>
<dc:subject>templating</dc:subject>
<dc:subject>MVC</dc:subject>
<dc:subject>view</dc:subject>
<issued>2009-11-02T14:00:00Z</issued>
<modified>2009-11-02T14:00:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Following up on last week&rsquo;s
<a href="/computers/programming/perl/modules/template-declare-documented.html" title="Template Declare Explained">release</a> of
<a href="http://search.cpan.org/perldoc?Template::Declare" title="Template::Declare on CPAN">Template::Declare</a>
0.41, this week I'm pleased to announce the release of a new
<a href="http://www.catalystframework.org/">Catalyst</a> view class,
<a href="http://search.cpan.org/perldoc?Catalyst::View::TD" title="Calyst::View::TD on CPAN">Catalyst::View::TD</a>.</p>

<p>Yes, I'm aware of
<a href="http://search.cpan.org/perldoc?Catalyst::View::Template::Declare">Catalyst::View::Template::Declare</a>.
As I <a href="/computers/programming/perl/modules/template-declare-documented.html" title="Template Declare Explained">mentioned</a>
last week, it doesn&rsquo;t make very good use of Template::Declare. I don&rsquo;t blame
<a href="http://blog.jrock.us/">jrock</a> for that, though; Template::Declare had very
poor documentation before 0.41. But now that it is properly documented and I
have a pretty solid grasp of how it works, I wanted to create a new Catalyst
View that could take proper advantage of its features.</p>

<p>If you're a Catalyst developer, chances are that you currently use
<a href="http://search.cpan.org/perldoc?Template" title="Template Toolkit on CPAN">Template Toolkit</a>
or <a href="http://search.cpan.org/perldoc?HTML::Mason" title="Mason on CPAN">Mason</a>
for your templating needs. So why should you consider
<a href="http://search.cpan.org/perldoc?Catalyst::View::TD" title="Calyst::View::TD on CPAN">Catalyst::View::TD</a>
for your next project? How about:</p>

<ul>
<li>Feature-parity with <a href="http://search.cpan.org/perldoc?Catalyst::View::TT" title="Catalyst::View::TT">Catalyst::View::TT</a>, the view class for Template Toolkit</li>
<li>Includes a <code>myapp_create.pl</code> helper for creating new template classes.</li>
<li>Intuitive, easy-to-use HTML and XML templating in Perl</li>
<li>All templates loaded at server startup time (great for forking servers like mod_perl)</li>
<li>Template paths that correspond to Controller URIs.</li>
</ul>


<p>If you weren&rsquo;t convinced by the first three points, that forth one is the
killer. It&rsquo;s the reason I wrote a new view. But here&rsquo;s an even better reason:
I'm going to show you exactly how to use it, right here in this blog post.</p>

<h3>A Simple Hello</h3>

<p>I'm borrowing from
<a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics" title="Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics">chapter 3</a>
of the Catalyst tutorial. First, create a new app:</p>

<pre>
$ catalyst.pl MyApp
cd MyApp
</pre>


<p>Then update the list of plugins in <code>MyApp.pm</code>:</p>

<pre>
use Catalyst qw/
    -Debug
    ConfigLoader
    Static::Simple
    StackTrace
/;
</pre>


<p>Now create a controller:</p>

<pre>
$ script/myapp_create.pl controller Books
</pre>


<p>Then edit it and add this controller (see
<a href="http://search.cpan.org/perldoc?Catalyst::Manual::Tutorial::03_MoreCatalystBasics" title="Catalyst Tutorial - Chapter 3: More Catalyst Application Development Basics">chapter 3</a>
if you need explanation about what this does):</p>

<pre>
sub list : Local {
    my ($self, $c) = @_;
    $c-&gt;stash-&gt;{books} = [];
    $c-&gt;stash-&gt;{template} = &#x27;/books/list&#x27;;
}
</pre>


<p>And now, create a view and a new template class:</p>

<pre>
$ script/myapp_create.pl view HTML TD
$ script/myapp_create.pl TDClass HTML::Books
</pre>


<p>Open <code>lib/MyApp/Templates/HTML/Books.pm</code> and add the <code>list</code> template:</p>

<pre>
my ($self, $args) = @_;
table {
    row {
        th { &#x27;Title&#x27;  };
        th { &#x27;Rating&#x27; };
        th { &#x27;Author&#x27; };
    };
    for my $book (@{ $args-&gt;{books} }) {
        row {
            cell { $book-&gt;{title}  };
            cell { $book-&gt;{rating} };
            cell { $book-&gt;{author} };
        };
    }
};
</pre>


<p>Then point your browser to http://localhost:3000/books/list. If you have
everything working so far, you should see a web page that displays nothing
other than our column headers for &ldquo;Title&rdquo;, &ldquo;Rating&rdquo;, and &ldquo;Author(s)&rdquo; &mdash; we
won&rsquo;t see any books until we get the database and model working below.</p>

<h3>A Few Comments</h3>

<p>The first thing I want to draw your attention to in this example is that
<code>list</code> template. Isn&rsquo;t it a thing of beauty? It&rsquo;s so easy for Perl hackers to
read. Compare it to the TT example from the tutorial (with the comments
removed, just to be fair):</p>

<pre>
&lt;tr&gt;&lt;th&gt;Title&lt;/th&gt;&lt;th&gt;Rating&lt;/th&gt;&lt;th&gt;Author(s)&lt;/th&gt;&lt;/tr&gt;
[% FOREACH book IN books -%]
  &lt;tr&gt;
    &lt;td&gt;[% book.title %]&lt;/td&gt;
    &lt;td&gt;[% book.rating %]&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
  &lt;/tr&gt;
[% END -%]
&lt;/table&gt;
</pre>


<p>I mean, which would <em>you</em> rather have to maintain? And this is an extremely
simple example. The comparison only becomes more stark when the HTML becomes
more complex.</p>

<p>The other thing I want to point out is the name of the template
class we created, <code>MyApp::Template::HTML::Books</code> and its
template, <code>list</code>. They correspond perfectly with the
controller, <code>MyApp::Controller::Books</code>, and its action
<code>list</code>. See the parity there? The URI for the action is
<code>/books/list</code>, and the template path, by coincidence is
also <code>/books/list</code>. Nice, huh? Thanks to this parity, you
can even remove the template specification in the controller, since by
default Catalyst will render a template with the same name as the
action:</p>

<pre>
sub list : Local {
    my ($self, $c) = @_;
    $c-&gt;stash-&gt;{books} = [];
}
</pre>


<p>This is the primary way in which
<a href="http://search.cpan.org/perldoc?Catalyst::View::TD" title="Calyst::View::TD on CPAN">Catalyst::View::TD</a>
differs from its
<a href="http://search.cpan.org/perldoc?Catalyst::View::Template::Declare">predeceossor</a>.
Whereas the latter would load all of the modules under the view&rsquo;s namespace
and shove all of their templates into root path, the former imports templates
under paths that correspond to their class names. Hence the match with
controller names.</p>

<h3>Stay Tuned</h3>

<p>It was kind of fun to subvert the Catalyst tutorial for my nefarious purposes.
Maybe I'll keep it up with more blog posts in the coming weeks that continues
to do so. Not only will it let me show off how nice Template::Declare
templates can be, but it will let me continue my rant against ORMs as well.
Stay tuned.</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/databases/postgresql/parse-pg-acls-with-pg-priv</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/databases/postgresql/parse-pg-acls-with-pg-priv.html" />
<title type="text/plain">Pg::Priv Hits CPAN (Thanks Etsy!)</title>
<dc:subject>PostgreSQL</dc:subject>
<dc:subject>privileges</dc:subject>
<dc:subject>permissions</dc:subject>
<dc:subject>ACLs</dc:subject>
<dc:subject>Etsy</dc:subject>
<dc:subject>Perl</dc:subject>
<dc:subject>Pg::Priv</dc:subject>
<issued>2009-10-30T23:59:00Z</issued>
<modified>2009-10-30T23:59:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Earlier this year, I was working on an administrative utility for
<a href="http://www.etsy.com/">Etsy</a> that validates PostgreSQL database
permissions. Of course, in order to verify that permissions were correct or
needed updating, I had to have a way to examine PostgreSQL ACLs, which are
arrays made of of strings that look like this:</p>

<pre><code>my $acl = [
   'miriam=arwdDxt/miriam',
   '=r/miriam',
   'admin=arw/miriam',
];
</code></pre>

<p>So following
<a href="http://www.postgresql.org/docs/current/static/sql-grant.html#SQL-GRANT-NOTES" title="PostgreSQL: “GRANT — Notes”">the documentation</a>, I wrote a module
that iterates over an ACL, parses each privilege string, and returns an object
describing it. Using it is pretty easy. If you wanted to see what the
permissions looked like on all the tables in a database, you could do it like
so:</p>

<pre>
#!/usr/bin/perl -w
use strict;
use warnings;
use DBI;
use Pg::Priv;

my $dbname = shift or die "Usage: $0 dbname\n";

my $dbh = DBI-&gt;connect("dbi:Pg:dbname=$dbname", 'postgres', '');
my $sth = $dbh-&gt;prepare(
    q{SELECT relname, relacl FROM pg_class WHERE relkind = 'r'}
);

$sth-&gt;execute;
print "Permissions for $dbname:\n";
while (my $row = $sth-&gt;fetchrow_hashref) {
    print "  Table $row-&gt;{relname}:\n";
    for my $priv ( Pg::Priv-&gt;parse_acl( $row-&gt;{relacl} ) ) {
        print '    ', $priv-&gt;by, ' granted to ', $priv-&gt;to, ': ',
            join( ', ', $priv-&gt;labels ), $/;
    }
}
</pre>

<p>And here's what the output looks like:</p>

<pre>
Permissions for bric:
  Table media__output_channel:
    postgres granted to postgres: UPDATE, SELECT, INSERT, TRUNCATE, REFERENCE, DELETE, TRIGGER
    postgres granted to bric: UPDATE, SELECT, INSERT, DELETE
  Table media_uri:
    postgres granted to postgres: UPDATE, SELECT, INSERT, TRUNCATE, REFERENCE, DELETE, TRIGGER
    postgres granted to bric: UPDATE, SELECT, INSERT, DELETE
  Table media_fields:
    postgres granted to postgres: UPDATE, SELECT, INSERT, TRUNCATE, REFERENCE, DELETE, TRIGGER
</pre>

<p>There are a bunch of utility methods to make it pretty simple to examine
PostgreSQL privileges.</p>

<p>And now, I'm pleased to announce the release yesterday of
<a href="http://search.cpan.org/perldoc?Pg::Priv" title="Pg::Priv on CPAN">Pg::Priv</a>. My thanks to Etsy for agreeing to the
release, and particularly to <a href="http://chaddickerson.com/">Chad
Dickerson</a> for championing it. This module is a little thing compared to
some things I've seen open-sourced by major players, but even the simplest
utilities can save folks mountains of time. I hope you find Pg::Priv
useful.</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/modules/template-declare-documented</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/modules/template-declare-documented.html" />
<title type="text/plain">Template::Declare Explained</title>
<dc:subject>perl</dc:subject>
<dc:subject>template</dc:subject>
<dc:subject>templating</dc:subject>
<dc:subject>Template::Declare</dc:subject>
<dc:subject>mixin</dc:subject>
<dc:subject>delegation</dc:subject>
<issued>2009-10-30T05:09:00Z</issued>
<modified>2009-10-30T05:09:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="text/html" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="escaped">
<![CDATA[<p>Today, <a href="http://blog.sartak.org/">Sartak</a> uploaded a new version of
<a href="http://search.cpan.org/perldoc?Template::Declare" title="Template::Declare on CPAN">Template::Declare</a>.
Why should you care? Well, in addition to the
<a href="http://justatheory.com/computers/programming/perl/xml-generation.html" title="Just a Theory: “Generating XML in Perl”">nice templating syntax</a>,
the new version features <em>complete documentation</em>. For everything.</p>

<p>This came about because I was trying to understand Template::Declare, with its
occasional mentioning of “mixins” and “paths” and “roots,” and I just wasn&rsquo;t
getting it out of the
<a href="http://search.cpan.org/~sartak/Template-Declare-0.40/lib/Template/Declare.pm" title="Template::Declare 0.40">existing documentation</a>.
Much of my confusion stemmed from how
<a href="http://search.cpan.org/perldoc?Catalyst::View::Template::Declare" title="Catslyst::View::Template::Declare on CPAN">Catalyst::View::Template::Declare</a>
used Template::Declare. So I started peppering
<a href="http://blog.fsck.com" title="Massively Parallel Procrastination">Jesse</a> with
questions and offering to fill in some gaps in the docs, and he was foolish
enough to give me a commit bit.</p>

<p>I was particularly interested in the <code>import_templates</code> and <code>alias</code> methods.
There was no documentation, and though there were tests, the two methods were
so similar that I could barely tell the difference. I also wasn&rsquo;t sure what
the point was, though I had ideas. So I asked a bunch of
<a href="http://lists.jifty.org/pipermail/jifty-devel/2009-September/002161.html">questions</a>
and, through the discussion, I started to put the pieces together. I wrote
more tests, and started refactoring things. I'd write some code, rename
things, move them around, combine things, and then see who screamed. Jesse and
Sartak were happy to run the Jifty test suite and even, I think, some
<a href="http://www.bestpractical.com/">Best Practical</a> internal stuff to see what I
broke. And then I'd think I got things just right and they would punch holes
in it again.</p>

<p>But it finally came together, I understood what the methods were trying to do,
and I documented the shit out of it. Then Sartak would copy-edit my docs,
verifying my interpretations, and help me to understand where I got things
wrong.</p>

<p>The new version features a glossary (useful for users of other templating
packages) and extended examples that demonstrate XUL output, postprocessing,
inheritance, and wrappers. And, most importantly, an explanation of aliasing
(think delegation) and mixins (using the new name for <code>import_templates</code>:
<code>mix</code>). I greatly appreciate the time the BPS team took to answer my noobish
questions. And their patience as I ripped things apart and built them up
again. The result is that, in addition to being better documented, the new
version&rsquo;s <code>alias</code> method creates build much better-performing and less
memory-intensive aliases.</p>

<p>So why was I doing all this? Well,
<a href="http://search.cpan.org/perldoc?Catalyst::View::Template::Declare" title="Catslyst::View::Template::Declare on CPAN">Catalyst::View::Template::Declare</a>
never seemed quite right to me. And in my discussions with the Jifty guys, it
seemed clear that its use of Template::Declare was <a href="http://lists.jifty.org/pipermail/jifty-devel/2009-September/002162.html">trying to alias</a>
kinda sorta, but not really. So as I tried to understand aliasing, I realized
that a new view class was needed for catalyst. So I endeavored to really
understand the features of Template::Declare so that I could do it right.</p>

<p>More news on that soon.</p>

<p>The upshot is that you have pretty nice control over mixing and aliasing
Template::Declare templates into paths. For example, if you have this template
class:</p>

<pre>
package MyApp::Templates::Util;
use base &#x0027;Template::Declare&#x0027;;
use Template::Declare::Tags;

template header =&gt; sub {
    my ($self, $args) = @_;
    head { title {  $args-&gt;{title} } };
};

template footer =&gt; sub {
    div {
        id is &#x0027;fineprint&#x0027;;
        p { &#x0027;Site contents licensed under a Creative Commons License.&#x0027; }
    };
};
</pre>

<p>You can mix those templates into your primary template class like so:</p>

<pre>package MyApp::Templates::Main;
use base &#x0027;Template::Declare&#x0027;;
use Template::Declare::Tags;
use MyApp::Template::Util;
mix MyApp::Template::Util under &#x0027;/util&#x0027;;

template content =&gt; sub {
    show &#x0027;/util/header&#x0027;;
    body {
        h1 { &#x0027;Hello world&#x0027; };
        show &#x0027;/util/footer&#x0027;;
    };
};
</pre>

<p>See how I've used the mixed in <code>header</code> and <code>footer</code> templates by referring to
them under the <code>/util</code> path? This gives the invocation of the other templates
the feel of calling
<a href="http://search.cpan.org/perldoc?HTML::Mason" title=" on CPAN">Mason</a> components or
invoking
<a href="http://search.cpan.org/perldoc?Template" title="Template Toolkit on CPAN">Template Toolkit</a>
templates. You can use these templates like so:</p>

<pre>
Template::Declare-&gt;init( dispatch_to =&gt; [&#x0027;MyApp::Templates::Main&#x0027;] );
print Template::Declare-&gt;show(&#x0027;/content&#x0027;);
</pre>

<p>So <code>MyApp::Templates::Main</code>&rsquo;s templates are in the &ldquo;/&rdquo; directory, so to speak,
while the <code>MyApp::Templates::Util</code>&rsquo;s templates are in the &ldquo;/utils&rdquo;
subdirectory. Pretty cool, eh?</p>

<p>So with this understanding in place, I had a much better feel for
Template::Declare, and could better think of it in normal templating terms.
Now I'm <em>this</em> much closer to my ideal Catalyst development environment. More
soon.</p>]]>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/modules/new-pod-simple</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/modules/new-pod-simple.html" />
<title type="text/plain">Pod::Simple 3.09 Hits the CPAN</title>
<dc:subject>Perl</dc:subject>
<dc:subject>POD</dc:subject>
<dc:subject>Pod::Simple</dc:subject>
<dc:subject>Allison+Randal</dc:subject>
<issued>2009-10-27T23:21:00Z</issued>
<modified>2009-10-27T23:21:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>I spent some time over the last few days helping Allison fix bugs and close
tickets for a new version of
<a href="http://search.cpan.org/perldoc?Pod::Simple" title="Pod::Simple on CPAN">Pod::Simple</a>. I'm not sure how I convinced Allison to suddenly
dedicate her day to fixing Pod::Simple bugs and putting out a new release. She
must've had some studies or Parrot spec work she wanted to get out of or
something.</p>

<p>Either way, it's got some useful fixes and improvements:</p>

<ul>
  <li><p>The XHTML formatter now supports tables of contents (via the
  poorly-named-but-consistent-with-the-HTML-formatter <code>index</code>
  parameter).</p></li>

  <li>
    <p>You can now reformat verbatim blocks via the
    <code>strip_verbatim_indent</code> parameter/method. Because you have to
    indent verbatim blocks (code examples) with one or more spaces, you end up
    with those spaces remaining in output. Just have a look at
    <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBix::Connector">an example</a> on search.cpan.org. See how the
    code in the Synopsis is indented? That's because it's indented in the POD.
    But maybe you don't want it to be indented in your final output. If not, you can 
    strip out leading spaces via <code>strip_verbatim_indent</code>. Pass in
    the text to strip out:</p>

    <pre>$parser-&gt;strip_verbatim_indent('  ');</pre>

    <p>Or a code reference that figures out what to strip out. I'm fond of
    stripping based on the indentation of the first line, like so:</p>

    <pre>
$new-&gt;strip_verbatim_indent(sub {
      my $lines = shift;
      (my $indent = $lines-&gt;[0]) =~ s/\S.*//;
      return $indent;
  });
</pre>
  </li>

  <li><p>You can now use the <code>nocase</code> parameter to
      Pod::Simple::PullParser to tell the parser to ignore the case of POD
      blocks when searching for author, title, version, and description
      information. This is a hack that Graham has used for a while on
      search.cpan.org, in part because I nagged him about my modules, which
      don't use uppercase <code>=head1</code> text. Thanks Graham!</p></li>

  <li><p>Fixed entity encoding in the XHTML formatter. It was failing to
      encode entities everywhere except code spans and verbatim blocks. Oops.
      It also now properly encodes <code>E&lt;sol&gt;</code> and
      <code>E&lt;verbar&gt;</code>, as well as numeric entities.</p></li>

  <li><p>Multiparagraph items now work properly in the XHTML formatter, as do
      text items (definition lists).</p></li>

  <li><p>A POD tag found inside a complex POD tag (e.g., <code>C&lt;&lt;&lt;
	C&lt;foo&gt; &gt;&gt;&gt;</code>) is now properly parsed as text and
	entities instead of a tag embedded in a tag (e.g.,
        <code>&lt;foo&gt;</code>). This is in compliance
        with <a href="http://search.cpan.org/perldoc?perlpod">perlpod</a>.</p></li>
</ul>

<p>This last item is the only change I think might lead to problems. I fixed
it in response to
a <a href="https://rt.cpan.org/Public/Bug/Display.html?id=12239" title="C&lt;&lt;&lt; C&lt;&lt;foo&gt;&gt; &gt;&gt;&gt; not rendered properly.">bug report</a> from Schwern. The relevant bit from
the <a href="http://search.cpan.org/perldoc?perlpod">perlpod</a> spec is:</p>

<blockquote>
    <p>A more readable, and perhaps more “plain” way is to use an alternate
       set of delimiters that doesn’t require a single “&gt;” to be escaped.
       With the Pod formatters that are standard starting with perl5.5.660,
       doubled angle brackets (“&lt;&lt;” and “&gt;&gt;”) may be used if and
       only if there is whitespace right after the opening delimiter and
       whitespace right before the closing delimiter! For example, the
       following will do the trick:</p>

    <pre>C&lt;&lt; $a &lt;=&gt; $b &gt;&gt;</pre>

    <p>In fact, you can use as many repeated angle‐brackets as you like so
       long as you have the same number of them in the opening and closing
       delimiters, and make sure that whitespace immediately follows the last
       ’&lt;’ of the opening delimiter, and immediately precedes the first
       “&gt;” of the closing delimiter. (The whitespace is ignored.) So the
       following will also work:</p>

    <pre>C&lt;&lt;&lt; $a &lt;=&gt; $b &gt;&gt;&gt;
C&lt;&lt;&lt;&lt;  $a &lt;=&gt; $b     &gt;&gt;&gt;&gt;</pre>

    <p>And they all mean exactly the same as this:</p>

    <pre>C&lt;$a E&lt;lt&gt;=E&lt;gt&gt; $b&gt;</pre>
</blockquote>

<p>Although all of the examples use <code>C&lt;&lt; &gt;&gt;</code>, it seems
pretty clear that it applies to all of the span tags (
<code>B&lt;&lt; &gt;&gt;</code>, <code>I&lt;&lt; &gt;&gt;</code>,
<code>F&lt;&lt; &gt;&gt;</code>, etc.). So I made the change so that tags
embedded in these “complex” tags, as comments in Pod::Simple call them, are
not treated as tags. That is, all <code>&lt;</code> and <code>&gt;</code>
characters are encoded.</p>

<p>Unfortunately, despite what the perlpod spec says (at least in my reading),
Sean had quite a few pathological examples in the tests that expected POD tags
embedded in complex POD tags to work. Here's an example:</p>

<pre>L&lt;&lt;&lt; Perl B&lt;Error E&lt;77&gt;essages&gt;|perldiag &gt;&gt;&gt;</pre>

<p>Before I fixed the bug, that was expected to be output as this XML:</p>

<pre>&lt;L to="perldiag" type="pod"&gt;Perl &lt;B&gt;Error Messages&lt;/B&gt;&lt;/L&gt;</pre>

<p>After the bug fix, it's:</p>

<pre>&lt;L content-implicit="yes" section="Perl B&amp;#60;&amp;#60;&amp;#60; Error E&amp;#60;77&amp;#62;essages" type="pod"&gt;&amp;#34;Perl B&amp;#60;&amp;#60;&amp;#60; Error E&amp;#60;77&amp;#62;essages&amp;#34;&lt;/L&gt;</pre>

<p>Well, there's a lot more crap that Pod::Simple puts in there, but the
important thing to note is that neither the <code>B&lt;&gt;</code> nor
the <code>E&lt;&gt;</code> is evaluated as a POD tag inside
the <code>L&lt;&lt;&lt; &gt;&gt;&gt;</code> tag. If that seems inconsistent at
all, just remember that POD tags still work inside non-complex POD tags (that
is, when there is just one set of angle brackets:</p>

<pre>L&lt;Perl B&lt;Error E&lt;77&gt;essages&gt;|perldiag&gt;</pre>

<p>I'm pretty sure that few users were relying on POD tags working inside
complex POD tags anyway. At least I hope so. I'm currently working up a patch
for blead that updates Pod::Simple in core, so it will be interesting to see
if it breaks anyone's POD. Here's to hoping it doesn't!</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/modules/dbix-connector-updated</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/modules/dbix-connector-updated.html" />
<title type="text/plain">DBIx::Connector Updated</title>
<dc:subject>DBIx::Connector</dc:subject>
<dc:subject>DBI</dc:subject>
<dc:subject>database</dc:subject>
<dc:subject>connection</dc:subject>
<dc:subject>connectivity</dc:subject>
<dc:subject>ping</dc:subject>
<dc:subject>Perl</dc:subject>
<dc:subject>transactions</dc:subject>
<issued>2009-10-21T17:37:00Z</issued>
<modified>2009-10-21T17:37:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>After much gnashing of teeth, heated arguments with @robkinon and @mst,
lots of deep thesaurus spelunking, and three or four iterations, I finally
came up with an an improved API
for <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on CPAN">DBIx::Connector</a> that I believe is
straight-forward and easy to explain.</p>

<p>Following up on
my <a href="/computers/programming/perl/modules/dbix-connector-methods.html" title="Suggest Method Names for DBIx::Connector">post</a> last week, I
explored, oh I dunno, a hundred different terms for the various methods? I've
never spent so much time
on <a href="http://www.thesaurus.com/">thesaurus.com</a> in my life. Part of
what added to the difficulty was that @mst seemed to think that there should
actually be three modes for each block method: one that pings, one that
doesn't, and one that tries again if a block dies and the connection is down.
So I went from six to nine methods with that assertion.</p>

<p>What I finally came up with was to name the three basic methods <code>run()</code>,
<code>txn_run()</code>, and <code>svp_run()</code>, and these would neither
ping nor retry in the event of failure. Then I added variations on these
methods that would ping and that would try to fix failures. I called these
“ping runs” and “fixup runs,” respectively. It was the latter term, “fixup,”
that had been so hard for me to nail down, as “retry” seemed to say that the
method was a retry, while “fixup” more accurately reflects that the method
would try to fix up the connection in the event of a failure.</p>

<p>Once I'd implemented this interface, I now had nine methods:</p>

<ul>
  <li><code>run()</code></li>
  <li><code>txn_run()</code></li>
  <li><code>svp_run()</code></li>
  <li><code>ping_run()</code></li>
  <li><code>txn_ping_run()</code></li>
  <li><code>svp_ping_run()</code></li>
  <li><code>fixup_run()</code></li>
  <li><code>txn_fixup_run()</code></li>
  <li><code>svp_fixup_run()</code></li>
</ul>

<p>This worked great. Then I went about documenting it. Jesus Christ what a
pain! I realized that all these similarly-named methods would require a lot of
explanation. I duly wrote up said explanation, and just wasn't happy with it.
It just felt to me like all the explanation made it too difficult to decide
what methods to use and when. Such confusion would make the module less likely
to be used -- and certainly less likely to be used efficiently.</p>

<p>So I went back to the API drawing board and, reflecting on @robkinyon's
browbeating about decorating methods and @mst's coming to that conclusion as
well, I finally came up with just three methods:</p>

<ul>
  <li><code>run()</code></li>
  <li><code>txn()</code></li>
  <li><code>svp()</code></li>
</ul>

<p>For any one of these, you can call it by passing a block, of course:</p>

<pre>
$conn-&gt;txn( sub { $_-&gt;do('SELECT some_function()') } );
</pre>

<p>In addition, you can now have any one of them run in one of three
modes: the default (no ping), “ping”, or “fixup”:</p>

<pre>
$conn-&gt;txn( fixup =&gt; sub { $_-&gt;do('SELECT some_function()') } );
</pre>

<p>It's <em>much</em> easier to explain the three methods in terms of how the
block is transactionally encapsulated, as that's the only difference between
them. Once that's understood, it's pretty easy to explain how to change the
“connection mode” of each by passing in a leading string. It even looks pretty
nice. I'm really happy with this</p>

<p>One thing that increased the difficulty in coming up with this API was that
@mst felt that by default the methods should neither ping nor try to fix up a
failure. I was resistant to this because it's not
how <a href="http://search.cpan.org/perldoc?Apache::DBI" title="Apache::DBI on CPAN">Apache::DBI</a> or
<a href="http://search.cpan.org/perldoc?DBI#connect_cached" title="DBI on CPAN"><code>connect_cached()</code></a> work: they always ping.
It turns out that <a href="http://search.cpan.org/perldoc?DBIx::Class" title="DBIx::Class on CPAN">DBIx::Class</a> doesn't cache connections
at all. I thought it had. Rather, it creates a connection and simply hangs
onto it as a scalar variable. It handles the connection for as long as it's in
scope, but includes no magic global caching. This reduces the action-at-a-distance
issues common with caching while maintaining proper <code>fork</code>- and
thread-safety.</p>

<p>At this point, I took a baseball bat to my desk.</p>

<p>Figuratively, anyway. I did at least unleash a mountain of curses upon @mst
and various family relations. Because it took me a few minutes to see it: It
turns out that DBIx::Class is right to do it this way. So I ripped out the
global caching from DBIx::Connector, and suddenly it made much more sense not
to ping by default -- just as you wouldn't ping if you created a DBI handle
yourself.</p>

<p>DBIx::Conector is no longer a caching layer over the DBI. It's now
a <em>proxy</em> for a connection. That's it. There is no magic, no implicit
behavior, so it's easier to use. And because it ensures <code>fork</code>- and
thread-safety, you can instantiate a connector and hold onto it for whenever
you need it, unlike using the DBI itself.</p>

<p>And one more thing: I also added a new method, <code>with()</code>. For
those who always want to use the same connection mode, you can use this method
to create a proxy object that has a different default mode. (Yes, a proxy for
a proxy for a database handle. Whatever!) Use it like this:</p>

<pre>
$conn-&gt;with('fixup')-&gt;run( sub { ... } );
</pre>

<p>And if you always want to use the same mode, hold onto the proxy instead of
the connection object:</p>

<pre>
my $proxy = DBIx::Connector-&gt;(@args)-&gt;with('fixup');

# later ...
$proxy-&gt;txn( sub { ... } ); # always in fixup mode
</pre>

<p>So while fixup mode is no longer the default,
as <a href="https://rt.cpan.org/Ticket/Display.html?id=47005" title="RT #47005: txn_do should provide a way to disable retry">Tim
requested</a>, but it can optionally be made the default, as DBIx::Class
requires. The <code>with()</code> method will also be the place to add other
global behavioral modifications, such as
DBIx::Class's <code>auto_savepoint</code> feature.</p>

<p>So for those of you who were interested in the first iteration of this
module, my apologies for changing things so dramatically in this release
(ripping out the global caching, deprecating methods, adding a new block
method API, etc.). But I think that, for all the pain I went through to come
up with the new API -- all the arguing on IRC, all the thesaurus spelunking --
that this is a really good API, easy to explain and understand, and easy to
use. And I don't expect to change it again. I might improve exceptions (use
objects instead of strings?) add block method exception handling (perhaps
adding a <code>catch</code> keyword?), but the basics are finally nailed down
and here to stay.</p>

<p>Thanks to @mst, @robkinyon, and @ribasushi, in particular, for bearing with
me and continuing to hammer on me when I was being dense.</p></div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/modules/dbix-connector-methods</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/modules/dbix-connector-methods.html" />
<title type="text/plain">Suggest Method Names for DBIx::Connector</title>
<dc:subject>Perl</dc:subject>
<dc:subject>DBI</dc:subject>
<dc:subject>database</dc:subject>
<dc:subject>DBIx::Connector</dc:subject>
<dc:subject>run</dc:subject>
<dc:subject>ping</dc:subject>
<dc:subject>methods</dc:subject>
<dc:subject>transaction</dc:subject>
<dc:subject>block</dc:subject>
<dc:subject>code+reference</dc:subject>
<issued>2009-10-13T19:25:00Z</issued>
<modified>2009-10-13T19:25:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>Thanks to feedback from Tim Bunce and Peter Rabbitson in a DBIx::Class <a href="https://rt.cpan.org/Ticket/Display.html?id=47005" title="RT #47005: txn_do should provide a way to disable retry">bug report</a>, I've been reworking <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on CPAN">DBIx::Connector</a>'s block-handling methods. Tim's objection is that the the feature of <code>do()</code> and <code>txn_do()</code> that executes the code reference a second time in the event of a connection failure can be dangerous. That is, it can lead to action-at-a-distance bugs that are hard to find and fix. Tim suggested renaming the methods <code>do_with_retry()</code> and <code>txn_do_with_retry()</code> in order to make explicit what's going on, and to have non-retry versions of the methods.</p>

<p>I've made this change in the <a href="http://github.com/theory/dbix-connector/" title="DBIx::Connector on GitHub">repository</a>. But I wasn't happy with the method names; even though they're unambiguous, they are also overly long and not very friendly. I want people to <em>use</em> the retrying methods, but felt that the long names make the non-retrying preferable to users. While I was at it, I also wanted to get rid of <code>do()</code>, since it quickly became clear that it could <a href="http://github.com/theory/dbix-connector/issues#issue/3" title="Issue #3: API is somewhat confusing">cause some confusion</a> with the DBI's <code>do()</code> method.</p>

<p>I've been thesaurus spelunking for the last few days, and have come up with a few options, but would love to hear other suggestions. I like using <code>run</code> instead of <code>do</code> to avoid confusion with the DBI, but otherwise I'm not really happy with what I've come up with. There are basically five different methods (using Tim's suggestions for the moment):</p>

<dl>
  <dt><code>run( sub {} )</code></dt>
  <dd>Just run a block of code.</dd>
  <dt><code>txn_run( sub {} )</code></dt>
  <dd>Run a block of code inside a transaction.</dd>
  <dt><code>run_with_retry( sub {} )</code></dt>
  <dd>Run a block of code without pinging the database, and re-run the code if it throws an exception and the database turned out to be disconnected.</dd>
  <dt><code>txn_run_with_rerun( sub {} )</code></dt>
  <dd>Like <code>run_with_retry()</code>, but run the block inside a transaction.</dd>
  <dt><code>svp_run( sub {} )</code></dt>
  <dd>Run a block of code inside a savepoint (no retry for savepoints).</dd>
</dl>

<p>Here are some of the names I've come up with so far:</p>

<style type="text/css">
#dbixc {
border-collapse: collapse;
border-right: 1px solid #CCC;
margin: 0 0 1em;
}

#dbixc th {
padding: 0 0.5em;
text-align: left;
border-left: 1px solid #CCC;
border-top: 1px solid #FB7A31;
border-bottom: 1px solid #FB7A31;
background: #FFC;
}

#dbixc td {
border-bottom: 1px solid #CCC;
padding: 0.5em;
border-left: 1px solid #CCC;
}
</style>
<table id="dbixc">
  <tr>
    <th>Run block</th>
    <th>Run in txn</th>
    <th>Run in savepoint</th>
    <th>Run with retry</th>
    <th>Run in txn with retry</th>
    <th>Retry Mnemonic</th>
  </tr>
  <tr>
    <td><code>run</code></td>
    <td><code>txn_run</code></td>
    <td><code>svp_run</code></td>
    <td><code>runup</code></td>
    <td><code>txn_runup</code></td>
    <td>Run assuming the db is up, retry if not.</td>
  </tr>
  <tr>
    <td><code>run</code></td>
    <td><code>txn_run</code></td>
    <td><code>svp_run</code></td>
    <td><code>run_up</code></td>
    <td><code>txn_run_up</code></td>
    <td>Same as above.</td>
  </tr>
  <tr>
    <td><code>run</code></td>
    <td><code>txn_run</code></td>
    <td><code>svp_run</code></td>
    <td><code>rerun</code></td>
    <td><code>txn_rerun</code></td>
    <td>Run assuming the db is up, rerun if not.</td>
  </tr>
  <tr>
    <td><code>run</code></td>
    <td><code>txn_run</code></td>
    <td><code>svp_run</code></td>
    <td><code>run::retry</code></td>
    <td><code>txn_run::retry</code></td>
    <td><code>::</code> means “with”</td>
  </tr>
</table>

<p>That last one is a cute hack suggested
by <a href="http://search.cpan.org/~rkinyon/" title="Rob Kinyon's CPAN distributions">Rob Kinyon</a> on IRC. As you can see, I'm pretty consistent
with the non-retrying method names; it's the methods that retry that I'm not
satisfied with. A approach I've avoided is to use an adverb for the non-retry
methods, mainly because there is no retry possible for the savepoint methods,
so it seemed silly to have <code>svp_run_safely()</code> to
complement <code>do_safely()</code> and <code>txn_do_safely()</code>.</p>

<p>Brilliant suggestions warmly appreciated.</p>
</div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/programming/perl/modules/dbix-connector</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/programming/perl/modules/dbix-connector.html" />
<title type="text/plain">Database Handle and Transaction Management with DBIx::Connector</title>
<dc:subject>Perl</dc:subject>
<dc:subject>DBI</dc:subject>
<dc:subject>DBix::Class</dc:subject>
<dc:subject>connection</dc:subject>
<dc:subject>DBIx::Connector</dc:subject>
<dc:subject>transactions</dc:subject>
<dc:subject>savepoints</dc:subject>
<issued>2009-10-05T23:11:00Z</issued>
<modified>2009-10-05T23:11:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>As part of my ongoing effort to wrestle Catalyst into working the way
that <em>I</em> think it should work, I've just
uploaded <a href="http://search.cpan.org/perldoc?DBIx::Connector" title="DBIx::Connector on the CPAN">DBIx::Connector</a> to the CPAN. See, I
was using <a href="http://search.cpan.org/perldoc?Catalyst::Model::DBI" title="Catalyst::Model::DBI the CPAN">Catalyst::Model::DBI</a>, but it turned
out that I wanted to use the database handle in places other than the Catalyst
parts of <a href="http://github.com/theory/circle/" title="Circle on GitHub">my app</a>. I was bitching about this to 
<a href="http://www.trout.me.uk/" title="Matt S Trout">mst</a> on #catalyst,
and he said that Catalyst::Model::DBI was actually a fork of DBIx::Class's
handle caching, and quite out of date. I said, “But this already exists. It's
called <a href="/computers/programming/perl/dbi-connect-cached-hack.html" title="Keep DBI's connect_cached From Horking Transactions"><code>connect_cached()</code></a>.” I believe his response was,
“OH FUCK OFF!”</p>

<p>So I started digging into what Catalyst::Model::DBI and DBIx::Class do to
cache their database handles, and how it differs from
<code>connect_cached()</code>. It turns out that they were pretty smart, in
terms of checking to see if the process had forked or a new thread had been
spawned, and if so, deactivating the old handle and then returning a new one.
Otherwise, things are just cached. This approach works well in Web
environments, including under <a href="http://perl.apache.org/">mod_perl</a>;
in forking applications, like <a href="http://search.cpan.org/perldoc?POE" title="POE on CPAN">POE</a> apps; and in plain Perl scripts. Matt said he'd
always wanted to pull that functionality out of DBIx::Class and then make
DBIx::Class depend on the external implementation. That way everyone could
take advantage of the functionality, including people like me who don't want
to use an ORM.</p>

<p>So I did it. Maybe it was crazy (mmmmm…yak meat), but I can now use the
same database interface in the Catalyst and POE parts of my application
without worry:</p>

<pre>
my $dbh = DBIx::Connector-&gt;connect(
    'dbi:Pg:dbname=circle', 'postgres', '', {
        PrintError     =&gt; 0,
        RaiseError     =&gt; 0,
        AutoCommit     =&gt; 1,
        HandleError    =&gt; Exception::Class::DBI-&gt;handler,
        pg_enable_utf8 =&gt; 1,
    },
);

$dbh-&gt;do($sql);
</pre>

<p>But it's not just database handle caching that I've included in
DBIx::Connector; no, I've also stolen some of the transaction management stuff
from DBIx::Class. All you have to do is grab the connector object which
encapsulates the database handle, and take advantage of
its <code>txn_do()</code> method:</p>

<pre>
my $conn = DBIx::Connector-&gt;new(@args);
$conn-&gt;txn_do(sub {
    my $dbh = shift;
    $dbh-&gt;do($_) for @queries;
});
</pre>

<p>The transaction is scoped to the code reference passed to
<code>txn_do()</code>. Not only that, it avoids the overhead of calling
<code>ping()</code> on the database handle unless something goes wrong. Most
of the time, nothing goes wrong, the database is there, so you can proceed
accordingly. If it is gone, however, <code>txn_do()</code> will re-connect and
execute the code reference again. The cool think is that you will never notice
that the connection was dropped -- unless it's still gone after the second
execution of the code reference.</p>

<p>And finally, thanks to some pushback from mst,
<a href="http://rabbit.us/">ribasushi</a>, and others, I added
<a href="http://en.wikipedia.org/wiki/Savepoint" title="Wikipedia: “Savepoint”">savepoint</a> support. It's a little different than that provided
by DBIx::Class; instead of relying on a magical <code>auto_savepoint</code>
attribute that subtly changes the behavior of <code>txn_do()</code>, you just
use the <code>svp_do()</code> method from within <code>txn_do()</code>. The
scoping of subtransactions is thus nicely explicit:</p>

<pre>
$conn-&gt;txn_do(sub {
    my $dbh = shift;
    $dbh-&gt;do('INSERT INTO table1 VALUES (1)');
    eval {
        $conn-&gt;svp_do(sub {
            shift-&gt;do('INSERT INTO table1 VALUES (2)');
            die 'OMGWTF?';
        });
    };
    warn "Savepoint failed\n" if $@;
    $dbh-&gt;do('INSERT INTO table1 VALUES (3)');
});
</pre>

<p>This transaction will insert the values 1 and 3, but not 2. If you call
<code>svp_do()</code> outside of <code>txn_do()</code>, it will call
<code>txn_do()</code> for you, with the savepoint scoped to the entire
transaction:</p>

<pre>
$conn-&gt;svp_do(sub {
    my $dbh = shift;
    $dbh-&gt;do('INSERT INTO table1 VALUES (4)');
    $conn-&gt;svp_do(sub {
        shift-&gt;do('INSERT INTO table1 VALUES (5)');
    });
});
</pre>

<p>This transaction will insert both 3 and 4. And note that you can nest
savepoints as deeply as you like. All this is dependent on whether
the database supports savepoints; so far, PostgreSQL, MySQL (InnoDB),
Oracle, MSSQL, and SQLite do. If you know of others, fork the
<a href="http://github.com/theory/dbix-connector/" title="DBIx::Connector on GitHub">repository</a>, commit changes to a branch, and send me a pull
request!</p>

<p>Overall I'm very happy with this module, and I'll probably use it in all my
Perl database projects from here on in. Perhaps later I'll build a model class
on it (something like Catalyst::Model::DBI, only better!), but next up, I plan
to finish documenting
<a href="http://search.cpan.org/perldoc?Template::Declare" title="Template::Declare on the CPAN">Template::Declare</a> and writing some
views with it. More on that soon.</p>


</div>
</content>
</entry>

<entry>
<id>tag:justatheory.com,2009:/computers/databases/postgresql/unicode-normalization</id>
<link rel="alternate" type="text/html" href="http://www.justatheory.com/computers/databases/postgresql/unicode-normalization.html" />
<title type="text/plain">Unicode Normalization in SQL</title>

<issued>2009-09-23T22:10:00Z</issued>
<modified>2009-09-23T22:10:00Z</modified>
<author>
  <name>David E. Wheeler</name>
</author>
<content type="application/xhtml+xml" xml:base="http://www.justatheory.com" xml:lang="en-us" xml:space="preserve" mode="xml">
<div xmlns="http://www.w3.org/1999/xhtml"><p>I've been peripherally aware of the need for unicode normalization in my
code for a while, but only got around to looking into it today. Although I
use <a href="http://search.cpan.org/perldoc?Encode" title="Encode on CPAN">Encode</a> to convert text inputs into Perl's internal form and UTF-8 or
an appropriate encoding in all my outputs, it does nothing about
normalization.</p>

<p>What's normalization you ask?</p>

<p>Well, UTF-8 allows some characters to be encoded in different ways. For
example, é can be written as either “&amp;#x00e9;”, which is a “precomposed
character,” or as “&amp;#x0065;&amp;#x0301;”, which is a combination of
“e” and ”́”. This is all well and good, but the trouble comes
when you want to compare values. Observe this Perl one-liner:</p>

<pre>
% perl -le 'print "\x{00e9}" eq "\x{0065}\x{0301}" ? "t" : "f"'
f
</pre>

<p>The same issue exists in your database. Here's an example from
PostgreSQL:</p>

<pre>
try=# select U&amp;'\00E9' = U&amp;'\0065\0301';
 ?column? 
----------
 f
(1 row)
</pre>

<p>If you have a user enter data in your Web app using combining characters,
and then another does a search with canonical characters, the search will
fail. This won't do at all.</p>

<p>The solution is to
<a href="http://en.wikipedia.org/wiki/Unicode_normalization" title="Wikipedia: “Unicode equivalence”">normalize</a> your Unicode data. In Perl, you can use the
<a href="http://search.cpan.org/perldoc?Unicode::Normalize" title="Unicode::Normalize on CPAN">Unicode::Normalize</a>, a C/XS module that
uses Perl's internal unicode tables to convert things as appropriate. For
general use the NFC normalization
is <a href="http://unicode.org/faq/normalization.html#2" title="Unicode Normaliztion FAQ: “Which forms of normalization should I support?”">probably
best</a>:</p>

<pre>
use Unicode::Normalize;
$string = NFC $string;
</pre>

<p>PostgreSQL offers no normalization routines. However, the SQL standard
mandates one (as of SQL 2008, at least). It looks like this:</p>

<pre>
&lt;normalize function&gt; ::= NORMALIZE &lt;left paren&gt; &lt;character value expression&gt; [ &lt;comma&gt; &lt;normal form&gt; [ &lt;comma&gt; &lt;normalize function result length&gt; ] ] &lt;right paren&gt;
&lt;normal form&gt; ::= NFC | NFD | NFKC | NFKD
</pre>

<p>The second argument defaults to <code>NFC</code> and the third, which
specifies a maximum length of the return value, is optional. The fact that it
looks like a function means that we can use PL/PerlU to emulate it in
PostgreSQL until a proper implementation makes it into core. Here's how:</p>

<pre>
CREATE OR REPLACE FUNCTION NORMALIZE(
    string TEXT,
    form   TEXT,
    maxlen INT
) RETURNS TEXT LANGUAGE plperlu AS $$
    use Unicode::Normalize 'normalize';
    my ($string, $form, $maxlen) = @_;
    my $ret = normalize($form, $string);
    elog(ERROR, 'Normalized value is too long') if length $ret &gt; $maxlen;
    return $ret;
$$;

CREATE OR REPLACE FUNCTION NORMALIZE(
    string TEXT,
    form   TEXT
) RETURNS TEXT LANGUAGE plperlu AS $$
    use Unicode::Normalize 'normalize';
    return normalize($_[1], $_[0]);
$$;

CREATE OR REPLACE FUNCTION NORMALIZE(
    string TEXT
) RETURNS TEXT LANGUAGE plperlu AS $$
    use Unicode::Normalize 'normalize';
    return normalize('NFC', shift);
$$;
</pre>

<p>I wrote a few tests to make sure it was sane:</p>

<pre>
SELECT U&amp;'\0065\0301' as combined,
       char_length(U&amp;'\0065\0301'),
       NORMALIZE(U&amp;'\0065\0301') as normalized,
       char_length(NORMALIZE(U&amp;'\0065\0301'));

SELECT NORMALIZE(U&amp;'\0065\0301', 'NFC')  AS NFC,
       NORMALIZE(U&amp;'\0065\0301', 'NFD')  AS NFD,
       NORMALIZE(U&amp;'\0065\0301', 'NFKC') AS NFKC,
       NORMALIZE(U&amp;'\0065\0301', 'NFKD') AS NFKD
;

SELECT NORMALIZE(U&amp;'\0065\0301', 'NFC', 1)  AS NFC,
       NORMALIZE(U&amp;'\0065\0301', 'NFD', 2)  AS NFD,
       NORMALIZE(U&amp;'\0065\0301', 'NFKC', 1) AS NFKC,
       NORMALIZE(U&amp;'\0065\0301', 'NFKD', 2) AS NFKD;

SELECT NORMALIZE(U&amp;'\0065\0301', 'NFD', 1);
</pre>

<p>And the output</p>

<pre>
 combined | char_length | normalized | char_length 
----------+-------------+------------+-------------
 é        |           2 | é          |           1
(1 row)

 nfc | nfd | nfkc | nfkd 
-----+-----+------+------
 é   | é   | é    | é
(1 row)

 nfc | nfd | nfkc | nfkd 
-----+-----+------+------
 é   | é   | é    | é
(1 row)

psql:try.sql:45: ERROR:  error from Perl function "normalize": Normalized value is too long at line 5.
</pre>

<p>Cool! So that's fairly close to the standard. The main difference is that
the form argument must be a string instead of a constant literal. But
PostgreSQL would likely support both. The length argument is also a literal,
and can be <code>10 charcters</code> or <code>64 bytes</code>, but for our
purposes, this is fine. The only downside to it is that it's slow: PostgreSQL
must convert its text value to a Perl string to pass to the function, and then
Unicode::Normalize turns it into a C string again to do the conversion, then
back to a Perl string which, in turn, is returned to PostgreSQL and converted
back into the text form. Not the quickest process, but may prove useful
anyway.</p>

<h3>Update: 1 Hour Later</h3>

<p>Note that this issue applies when
using <a href="http://www.postgresql.org/docs/current/static/textsearch.html" title="PostgreSQL Documentation: Full Text Search">full text search</a>, too.
Alas, it does not normalize unicode charaters for you:</p>

<pre>
try=# select to_tsvector(U&amp;'\00E9clair') @@ to_tsquery(U&amp;'\0065\0301clair');
 ?column? 
----------
 f
(1 row)
</pre>

<p>But normalizing with the functions I introduced does work:</p>

<pre>
try=# select to_tsvector(U&amp;'\00E9clair') @@ to_tsquery(normalize(U&amp;'\0065\0301clair'));
 ?column? 
----------
 t
(1 row)
</pre>

<p>So yes, this really can be an issue in your applications.</p></div>
</content>
</entry>


</feed>
