DBIC 0.7 で has-many な nested multi-step prefetch がうまくイカネ
- 'author' has-many 'books'
- 'book' has-many 'chapters'
みたいなありがちな DB で
- 2 authors
- each author has 2 books
- each book has 3 chapters
みたいなテーブルを作ってMulti-step-prefetch をためしてみたんですけど,
my @authors = $db->resultset('author')->search( { }, { prefetch => { 'book' => 'chapter' }, }, )->all; foreach my $author (@authors) { print $author->name, "\n"; foreach my $book ($author->books) { print "\t", $book->name, "\n"; foreach my $chapter ($book->chapters) { print "\t\t", $chapter->name, "\n"; } } }
の結果が,
Larry Wall Programming Perl C1: An Overview of Perl C2: Bits and Pieces C3: Unary and Binary Operators Perl Resource Kit C2: Programming with Perl Modules C3: Advanced Perl Programming Damian Conway Object Oriented Perl C1: Introduction of Object Oriented Programming C2: Introduction of Perl Programming C3: Object Oriented Perl Programming
chapter 1個と book 1個が lost してる。吐いている SQL は問題なさそうなので(CLI でためしたらうまくとれるんで)オブジェクトの結果からの再構築がうまくいってないぽいです。コードが追いづらかったんで報告してない。
いまのところ has-many なクエリを多段 prefetch するのはあんましよろしくない(そもそも resultset_attributes な条件つけたりすると競合しそうだし)みたいです。
おまけ
has-many な関連レコードを取得するとき,なーんとなく primary column(s) 順にソートされてることを期待してたんですけどもちろんそんなことはないんですよね,ええ。今日はまりました。
そんなとき有用なのが,id:nekokak さんご推薦の resultset_attributes
(resultset_attributes - Hatena::Diary::Neko::kak 500 Internal Server Error)。
ですが私みたいに全テーブルの primary key に id のように同じ名前をつける癖のある人は,
__PACKAGE__->resultset_attributes({ order_by => 'me.id'});
のように「me.」をつけたほうがベター。search_related とかすると id という名称が ambiguous になってしまうんで。ただ弊害はあるかもしんない。