DBI 自身の TRACE

あけましておめでとうございます。


新年も RT にあがっているパッチをあてながら DBIx::Simple 1.26 を使っています*1

以前から書いてるとおり DBIx::Simple + SQL::Abstract は小粋ですばらしいんですが,吐いた SQL 文を調べる機能がありません。どうせ DBI 自体にトレース機能あるんじゃね?と思ってドキュメントを見たら,やっぱりありました

my $db = DBIx::Simple->connect( ... );
$db->dbh->trace(1);
#$db->dbh->trace(1, 'sql.log');  # ログファイルを指定する場合

出力先としては STDOUT, STDERR か何らかのファイル名を指定することしかできないのでロガー等を通して出すことができません。あくまで困ったときの知恵ということで。

ちなみにログレベル 1*2の出力例は,

    DBI::db=HASH(0x9e53990) trace level set to 0x0/1 (DBI @ 0x0/0)
        in DBI 1.53-ithread (pid 5275)
    <- prepare('DELETE FROM items')= DBI::st=HASH(0x9e53ae0)
           at Simple.pm line 141
    <- execute= '0E0' at Simple.pm line 160
    <- finish= 1 at Simple.pm line 256
    <- prepare('INSERT INTO items (handle, id, name, short_name)
           VALUES (?, ?, ?, ?)')
       = DBI::st=HASH(0xa5f6b0c) at Simple.pm line 141
    <- execute('180' '1' ...)= 1 at Simple.pm line 160
    <- finish= 1 at Simple.pm line 256
    <- execute('180' '2' ...)= 1 at Simple.pm line 160
    <- finish= 1 at Simple.pm line 256
    <- execute('180' '3' ...)= 1 at Simple.pm line 160
    <- finish= 1 at Simple.pm line 256

こんな出力が大量に出て焦ります。「...」で省略されている部分は「$DBI::neat_maxlen」をいじると省略させずに出すこともできます。

なお INSERT してる部分のコードは,

foreach my $line (@data) {
    my @cells = split ',', $line;
    my %rec   = map { $_ => (shift @cells) } @fields;
    $db->insert('items', \%rec);
}

こーんな感じの適当なコード(つまりいちいち prepare せずに毎度毎度レコード用構造体を作っている)なんですが,同じフィールド群への INSERT だと自動的に prepare したものを再利用してくれるところが DBIx::Simple のやはり小粋なところですね*3

*1:メンテナがお忙しいのか,モノが素晴らしいだけにもったいないですね

*2:レベル1で充分とドキュメントにもかいてます

*3:DBIx::Simple::query() に該当コードが潜んでます