DBICでハマらないために Vol.1

| コメント(0)

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のイテレータを構築しやすいようにだと思われます。
結果

ピクチャ 3-3

ハマるポイントは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がイテレータを構築するに期待していない並びで結果が返ってしまいます。

ピクチャ 2-3
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がイテレータを構築しやすいように、配慮してあげること。

コメントする