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 になってしまうんで。ただ弊害はあるかもしんない。