むむ
create table playlist ( id integer not null, song integer not null, timestamp integer not null, primary key (id) );
create table song (
id integer not null,
name text,
artist integer not null,
album integer not null,
parimary key (id)
);
create table album (
id integer not null,
name text,
artist integer not null,
primary key (id)
);
create table artist (
id integer not null,
name text,
primary key (id)
);
とかって DB(SQLite) 構成で、
package DBIC::Playlist;
use base 'DBIx::Class::Core';
__PACKAGE__->belongs_to( song => 'DBIC::Song' );
package DBIC::Song;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( playlists => 'DBIC::Playlist' );
__PACKAGE__->belongs_to( artist => 'DBIC::Artist' );
__PACKAGE__->belongs_to( album => 'DBIC::Album' );
package DBIC::Album;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( songs => 'DBIC::Song' );
__PACKAGE__->belongs_to( artist => 'DBIC::Artist' );
package DBIC::Artist;
use base 'DBIx::Class::Core';
__PACKAGE__->has_many( songs => 'DBIC::Song' );
__PACKAGE__->has_many( albums => 'DBIC::Album' );
こうしたとして、ここで最新10件の playlist を取得したいとするとき、
my $playlists = DBIC::Playlist->search( {}, { order_by => 'timestamp desc', rows => 10 } );
とかすると $playlists->first->song
とか他のテーブルのもの読みにいくときにいちいち SQL が発行されるのであれよね。
ここで
my $playlists = DBIC::Playlist->search( {}, { order_by => 'timestamp desc', rows => 10, prefetch => [qw/song/] } );
とかすれば song テーブルは最初の SQL で JOIN して一緒に持ってきてくれる。
それはいいんだけど、その先の song.album とかもとってきてほしいんだけど、むりっすか!
この状況でたとえばテンプレート内で
[% WHILE (playlist = playlists.next) %]
album: [% playlist.song.artist.name %]
[% END %]
とかやると毎回 artist テーブルにクエリ投げる SQL がよばれるわけですよ。かっけぇ。。
どーすんのがいいのだろう。