Morris君の中身を書き換えてAnyEvent::DBIにしてみたわけだが、一個だけはまった部分があったので、メモっておく。

例えば以下のようなコードをAnyEvent::DBIを使うように変更したいとする。
use strict; use DBI; my $dbh = DBI->connect('dbi:SQLite:dbname=test.db'); $dbh->do( "CREATE TABLE IF NOT EXIST t1 (c1 int not null, c2 int not null)"); $dbh->do( "DELETE FROM t1"); for my $i (0..10) { $dbh->do( "INSERT INTO t1 (c1, c2) VALUES (?, ?)", $i, $i * 2); } my $sth = $dbh->prepare("SELECT * FROM t1"); # まぁ本当ならbind_columns使うけど while ( my $row = $sth->fetchrow_arrayref ) ) { print "c1 = $row->[0], c2 = $row->[1]\n"; }
これをまずさくっと以下のようにすると動かない
use strict; use AnyEvent::DBI; my $dbh = AnyEvent::DBI->new( "dbi:SQLite:dbname=test.db", undef, undef, undef, exec_server => 1, ); $dbh->exec( "CREATE TABLE IF NOT EXIST t1 (c1 int not null, c2 int not null)"); $dbh->exec( "DELETE FROM t1"); for my $i (0..10) { $dbh->exec( "INSERT INTO t1 (c1, c2) VALUES (?, ?)", $i, $i * 2); } my $cv = AnyEvent->condvar; $dbh->exec("SELECT * FROM t1", sub { my ($dbh, $rows, $rv) = @_; foreach my $row (@$rows) { print "c1 = $row->[0], c2 = $row->[1]\n"; } $cv->send; }); $cv->recv;

理由はシンプル。exec()の最後の引数としてコールバックを指定していないから。もちろん、本来であれば一個一個戻り値とかを確認すべきなんだけど、とりあえず動かしたい場合とかあるじゃない。そういう場合に結構はまりがちなので、ここは何もしない空のコールバックを用意する
use strict; use AnyEvent::DBI; my $noop = sub {}; my $dbh = AnyEvent::DBI->new( "dbi:SQLite:dbname=test.db", undef, undef, undef, exec_server => 1, ); $dbh->exec( "CREATE TABLE IF NOT EXIST t1 (c1 int not null, c2 int not null)", $noop); $dbh->exec( "DELETE FROM t1", $noop); for my $i (0..10) { $dbh->exec( "INSERT INTO t1 (c1, c2) VALUES (?, ?)", $i, $i * 2, $noop); } my $cv = AnyEvent->condvar; $dbh->exec("SELECT * FROM t1", sub { my ($dbh, $rows, $rv) = @_; foreach my $row (@$rows) { print "c1 = $row->[0], c2 = $row->[1]\n"; } $cv->send; }); $cv->recv;
ちょっぴり面倒くさいね!