読者です 読者をやめる 読者になる 読者になる

Sequelの罠

Sequel の罠っぽい挙動にハマったのでメモ。

次のようなテーブル a, b, c, d がありまして、

mysql> select * from a;
+------+
| id   |
+------+
|    1 |
+------+
mysql> select * from b;
+------+
| id   |
+------+
|    2 |
+------+
mysql> select * from c;
+------+
| id   |
+------+
|    3 |
+------+
mysql> select * from d;
+------+
| id   |
+------+
|    4 |
+------+

このテーブルを結合して、こういう結果を取り出そうと思って、

mysql> select a.id,b.id,c.id,d.id from a join b join c join d;
+------+------+------+------+
| id   | id   | id   | id   |
+------+------+------+------+
|    1 |    2 |    3 |    4 |
+------+------+------+------+

Sequel で書いてみたんですよ。ところがこんな結果に。

DB[:a].join(:b).join(:c).join(:d).get([:a__id, :b__id, :c__id, :d__id])
#=> [4, 4, 4, 4]

発行されているクエリはまともでした。

SELECT `a`.`id`, `b`.`id`, `c`.`id`, `d`.`id` FROM `a` INNER JOIN `b` INNER JOIN `c` INNER JOIN `d` LIMIT 1

どうやら、配列としてレコードを取り出す場合でも、内部的にはカラム名をキーとした Hash が使われてるのが原因のようでした。

なので、カラムにちゃんと別名をつけてやればうまくいきます。

DB[:a].join(:b).join(:c).join(:d).get([:a__id___a, :b__id___b, :c__id___c, :d__id___d])
#=> [1, 2, 3, 4]

Hash として取り出すときには気をつけてたんですけど、配列として取り出す時にもカラム名が影響するとは…。

で、過去に書いたコードを見てみたらちゃんと別名つけてたりしたんで知ってたはずなんだけど、しばらくかかないと忘れちゃうなぁ。