むむ

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 がよばれるわけですよ。かっけぇ。。

どーすんのがいいのだろう。

by typester / at 2005-12-25T13:30:00 / perl / Comments(0)