siki siki - 4 months ago 21
Scala Question

Slick left/right/outer joins with Option

In the Slick examples there are a few examples of joining where one of the resulting columns can be nulls, as it can be the case when doing left, right, or outer joins. For example:

val explicitLeftOuterJoin = for {
(c, s) <- Coffees leftJoin Suppliers on (_.supID === _.id)
} yield (c.name, s.name.?)


But what if I want to return the entire mapped object? What I mean is:

val explicitLeftOuterJoin = for {
(c, s) <- Coffees leftJoin Suppliers on (_.supID === _.id)
} yield (c, s.?)


This doesn't seem to work as it complains about "could not find implicit value for evidence parameter of type scala.slick.lifted.TypeMapper[Suppliers]". Basically I'd like it to return a list of tuple of (Coffee, Option[Supplier])

Why doesn't this work and what's the fix for it? Especially, since this works fine:

val q = for {
c <- Coffees
s <- Suppliers
} yield (c, s)


(I know that's an inner join)

Answer

UPDATE: This will be solved and simply work in Slick 3.0 coming end of 2014, no need anymore for the following workaround

This is a limitation of Slick at the moment. You have to call .? on every column individually. You can however place a function called ? in the table class that does this in a central place and thereby get .? on complete rows. This play-slick example code contains a generic solution involving some generated code. We also have a PR that adds auto-generation of a ? method lined up.

In the long run we will support a variant of outer joins in Slick where Slick is fully aware of the types involved and you do not need to specify .? anywhere. For now we have to live with workarounds involving code generation.