prefetch(multi)した際は、order_byに気をつけること。
$schema->resultset('Area')->search(
{
},
{
prefetch => 'prefectures',
}
);
この場合DBICはイテレータ、AreaとArea->Prefecturesに付随するデータをSQL一文で取得するわけです。
prefecturesはareaにとってhas_many(multi)です。
SQLはこんなかんじ。
SELECT me.id, me.name, prefectures.id, prefectures.hira_name,
prefectures.name,
prefectures.ascii_name, prefectures.abbr_name, prefectures.area_id,
prefectures.position FROM area me LEFT JOIN prefecture prefectures
ON ( prefectures.area_id = me.id ) ORDER BY prefectures.area_id
order_byが自動的に付加されています。DBICがArea->Prefecturesのイテレータを構築しやすいようにだと思われます。
結果
ハマるポイントはorder_byを指定した場合。上のを基にしてみます。
$schema->resultset('Area')->search(
{
},
{
prefetch => 'prefectures',
order_by => 'prefectures.id',
}
);
これでAreaイテレータを $area_rs->next とやっていくと
問題がおこります。(素直というべきか・・・)
SQLはこんなかんじ。
SELECT me.id, me.name, prefectures.id, prefectures.hira_name,
prefectures.name,
prefectures.ascii_name, prefectures.abbr_name, prefectures.area_id,
prefectures.position FROM area me LEFT JOIN prefecture prefectures
ON ( prefectures.area_id = me.id )
ORDER BY prefectures.id, prefectures.area_id
ORDER BY prefectures.id, prefectures.area_id ではDBICがイテレータを構築するに期待していない並びで結果が返ってしまいます。
me.id が 3 -> 2 -> 3 となっている。
つられて $area_rs->next が 1 -> 2 -> 3 -> 2 -> 3 昇ったり降りたりするんです。
正解は
$schema->resultset('Area')->search(
{
},
{
prefetch => 'prefectures',
order_by => ['me.id'. 'prefectures.id'],
}
);
prefetch(multi) & order_byした際は、DBICがイテレータを構築しやすいように、配慮してあげること。