« はてなブックマークのコメント欄のようなものをParseするモジュール | メイン | メモ&カレンダーWebアプリケーションつくりました。 »

Class::DBI::SweetでのJOIN

Class::DBI::Sweetのjoinをつかった検索を試してみた。
ソースコードは作っているアプリケーションからの抜きだしなので足りないところがあるかも。

EntryとそのTagを想定して、

package Entries;

__PACKAGE__->table('entries');
__PACKAGE__->columns(All=>qw/id title text created_on/);

__PACKAGE__->has_many("tags"=>'Tags');

1;

package Tags;

__PACKAGE__->table('tags');
__PACKAGE__->columns(All=>qw/id entry_id tag/);

__PACKAGE__->has_a('entry_id'=>'Entries');

1;

の2つのクラスを作成。
例えば、「Perl」というTagを含むEntryがあるとして、それを検索するには

my ($pager,$entries) = Entries->page({
    'tags.tag'=>'perl'
},{
    rows=>10,page=>1,
    order_by=>'created_on desc'
});

というのでOK。「tags.tag」でjoinを指定できます。「tags」の部分はテーブル名ではなくhas_manyで指定したリレーション名です。

このときに発行されるSQLは

SELECT me.id, me.title, me.text, me.created_on
FROM   entries me, tags tags
WHERE  ( tags.tag = 'Perl' ) AND me.id = tags.entry_id ORDER BY created_on desc LIMIT 0, 10

このようになっている。

ちなみにどんなSQLが発行されているか確認する為には、環境変数DBI_TRACEを2にすればいいらしい。Class::DBIのwikiに書いてありました

$ENV{DBI_TRACE}=2;

とどっかに書くとトレースされます。出力される情報は結構多いです。

DBIx::Classはこの辺(joinの周り)がちょっと異なっていてよくまだわからない。

コメント

こんばんは。
DBIx::ClassでのSQLトレースですが、例えば、、、
DBI->trace(2 => "./logfile");
でlogfileに出力されます。
Class::DBIのwikiに書いてあるのも、結局はDBI自体のトレースを使ってます。
問題は、SQLが長くなった場合、全てのSQLをこの手法では拾えないところですね。これ、業務では結構痛いです。

最後の文章はのかかる部分は全体のつもりだったのですが、いつもながらわかりにくい文章ですね。すみません。

DBIx::Classのログは
$ENV{DBIX_CLASS_STORAGE_DBI_DEBUG}=1;
これでもいけます。warningに出力ですけど。
DBIはDBIなんでDBI->trace(2 => "./logfile");も使えますね。

コメントを投稿