Filter::SQL 作った - id:kazuhookuのメモ置き場にある、Filter::SQLが使いやすくて仕方がないという話。
前にも書いたけれど私はPerlのデータベースプログラミングに苦手意識がある。SQLもPerlも人並みにはできるけれど、その両方がまざったのはどうもだめだ。
だいたい、こちらはSELECTだけをすればいいのに
use 5.010;
use DBI;
my $dbh = DBI->connect("dbi:SQLite:dbname=foo.db");
my $sth = $dbh->prepare("SELECT * FROM table WHERE bar > 1");
$sth->execute;
while ( my $row = $sth->fetch ) {
say join "\t", @$row;
}
のような呪文を書かなくてはならないのは苦痛だ。connectはわかるけれどprepareやexecuteは人間のするべき仕事とは思えない。何よりもSQL文と出力を表示するところが離れているのが嫌だ。
SQLを書かずに全部Perlですませればいいかというと、必ずしもそうでもない。SQLを書かないようにするとSQL::Abstractを使ったりして
my ( $stmt, @bind ) = $sql->select( 'table', '*', { bar => { '>', 1 } } );
となるが、これも私の頭のキャパシティを超える。
PerlはPerl、SQLはSQLがそこそこ分離され「見た目にわかりやすい」ものをずっと探し求めていた。そこにFilter::SQLというモジュールの登場である。先の例はこう書き替えられる。
use 5.010;
use DBI;
use Filter::SQL;
Filter::SQL->dbh(DBI->connect("dbi:SQLite:dbname=foo.db"));
for my $row (SELECT * FROM table WHERE bar > 1;) {
say join "\t", @$row;
}
これです、私の長年求めていたものは。SELECTがそのまま書けて、さらにそのまま配列が返る。書きやすくて仕方がないし読むのもわかりやすい。SELECT文のまわりに引用符がいらないのも良い。SELECTの最後のセミコロンは一つのおまじないだけれど、prepareしてexecuteしてfetchするよりずっといい。DBIx::Simpleよりもさらにシンプルだ。
ソースを見てみるとFilter::Simpleを使った小さいモジュール。明快に書いてあってこんなことなら自分で書けばよかった、と思ったがそれを人はコロンブスの卵と呼ぶ。
追記(4月20日)
prepare,execute,fetchを一気にやるなら素のDBIでも selectall_hashref とか
コメントありがとうございます。どっちかというとselectall_araryrefのほうが近くて(Filter::SQLの内部で使われています)、上のスクリプトは
my $dbh = DBI->connect("dbi:SQLite:dbname=foo.db");
for my $row ( @{ $dbh->selectall_arrayref("SELECT * from table WHERE bar > 1") } ) {
say join "\t", @$row;
}
と書きかえられます。
SQL::Filterのほうが明らかにインターフェイスが優れていますが(私の好みの問題でもあります)、企業などでモジュールをインストールできないといった方はDBIそのままでもそれほど悪くない、ということだと思います。
SELECTするためにDBIを素で使うことがほとんどないのでselectall_arrayrefなんて忘れてました……ごめんなさい:)
0 件のコメント:
コメントを投稿