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;
ちょっぴり面倒くさいね!
コメント