ただ日々を記すもの

意識高めを装うことができます

【Scala, Slick】Slickのmonadic joinには上限があるっぽい

コンパイルエラーがないのに、Slickのコードで実行時にエラーが発生していました。

いろいろ調べてみたのですが、どうやら monadic join にはjoinできるテーブルに上限があるようです。

monadic joinに関して

細かいことは、今後まとめます。

使い方は2種類。flatMapを使う場合とforを使う場合。

とりあえず、↓がドキュメント

公式ドキュメント

ちなみにこちらのドキュメントでは、implict inner join と紹介されている

people.flatMap(p =>
  addresses.filter(a => p.addressId === a.id)
           .map(a => (p.name, a.city))
)
val monadicCrossJoin = for {
  p <- people
  a <- addresses
} yield (p.name, a.city)

使い方としては、こんな感じになります。

複数のテーブルをjoin!!

使い方がわかればあとは、好きに使うだけ。

複数テーブルを使うときは、↓こんな感じ。

val monadicCrossJoin = for {
  c <- coffees
  s <- suppliers
  p <- people
  pd <- peopleDetal
} yield (c, s, p, pd)

….って使い方をしたいんですが、 実はこれできないんです。

どうやらmonadic join でjoinできるテーブルには上限があるようなんです。(詳細はこちら

対応策

じゃあ、一体どうやって4つ以上のテーブルをjoinすればいいの?

対応策は、至極簡単で、そもそもmonadic join だけで対応するのを諦めることです。

val monadicCrossJoin = for {
  (c, s) <- coffees.join(suppliers)
  p <- people
  pd <- peopleDetal
} yield (c, s, p, pd)

↑のような感じで記述すれば問題なく使用できます。

ちょっと説明すると、

val crossJoin = for {
  (c, s) <- coffees join suppliers
} yield (c.name, s.name)

coffees join suppliers の部分はapplicative join です。

生成されるSQL文に違いがあり、

monadic join

SELECT c.name, s.name FROM coffees c, suppliers s

applicative join

SELECT c.name, s.name FROM coffees c join suppliers s

となります。

まとめ

バグなのかはいまいちわからないですが、 とりあえず対応策を書いておきました。

参考になれば幸いです。
あと、細かく知ってる方いたら具体的になんでダメなのか教えてもらえるとすごく嬉しい