わかった! $rs->search() をつなげて検索をかけていたのだが、これで最初のsearch()だけでpageとrowsを指定していたにもかかわらず、searchの実装として以下のようになっているため、offsetがどんどん増えて行ってしまう:



my $rs = DBIx::Class::Resultset->new(..., { page => $p, rows => $r });
# この時点で、$rs->{attrs}{page}, $rs->{attrs}{rows}を元に$rs->{attrs}{offset}
# が$p と $rを元にして計算される

# 条件1で検索
$rs = $rs->search( ... ); # ここでD::C::ResultSet->new がまた呼ばれる

# 条件2で検索
$rs = $rs->search( ... ); # さらにもう一回newが呼ばれる

ポイントはそれぞれのsearchの呼び出しの時にnewが呼ばれて、offsetが更新される事。つまり



offset += row * (page - 1);

として毎回計算されるわけだ。でもrowとpageは毎回同じものがコンストラクタに渡されるから、searchの度にoffsetが足される。そりゃあページングもずれます。


というわけで、教訓:ページングは一番最後に指定!



my $rs = $schema->resultset('Hoge');
$rs = $rs->search( \%where1 );
$rs = $rs->search( \%where2 );
$rs = $rs->search( \%where3 );

# で、最後に
$rs = $rs->search( undef, { rows => $rows, page => $page });