How does Slick translate code such as:
val q2 = for {
c <- Coffees if c.price < 9.0
s <- Suppliers if s.id === c.supID
} yield (c.name, s.name)
for(t <- q2) println(" " + t._1 + " supplied by " + t._2)
Into JDBC?
Does it use Scala Virtualized? Does it use some other method?
Slick’s stable API achieves this via what it calls lifted embedding. Your example is clearly using the stable API (as you use
===for equality and not==).The beauty of Slick (and in turn Scala) is that – this much is achieved without using macros or Scala-Virtualized. (Side Note: Slick’s experimental API does use macros – and this will allow you to use
==instead of===oris)The translation to SQL is achieved using:
Scala’s
forcomprehension syntax, which is translated to method calls.Tables defined in Slick are Monads – they have the magic
foreach,map,flatMap, andfiltermethods which allow them to be expressed infor‘loops’ while Scalatranslates them to method calls (as correctly illustrated in the code
provided by the other answer by @emil-ivanov).
As with regular Scala collections, the
foris syntactic sugar for nestedmethod calls to
flatMap/mapandfilter; unlike regular collections,the Slick
Tableobjects’ versions ofmapandfilterreturn representationsof a query, building it along with every filter condition (
if) or join(as in
s <- Suppliers if s.id is c.supID)So the type of
q2is not your usual collection (as a for comprehension in Scalais typically used to return), but rather a representation of a query.
(Just as the Scala Option Monad also works with
forcomprehensions despitenot being a ‘collection’ (in the way that
ListorMapis))You can see the underlying query with
q2.selectStatement.Scala’s implicit lifting –
c.priceis not anIntbut rather a representation ofa column value – so the expression
c.price < 9.0becomesc.price.<(Const(9.0))(an
Intis lifted to the desired type), and<is a just a method of theclass that represents
c.price, aColumn. The<methoddoes not do what
<usually does (in the case of plainInts) – it simply returnsa representation of the SQL AST corresponding to
price < 9that becomes part ofthe SQL that is generated and sent off to JDBC to execute.
There’s a whole lot else going on, in terms of details, but I think the query monad and the implicit lifting are the chief ingredients.