How does Scala Slick translate Scala code into JDBC?
scala, slick
Solution
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 `===` or `is`)
The translation to SQL is achieved using:
Scala's `for` comprehension syntax, which is translated to method calls. Tables defined in Slick are Monads - they have the magic `foreach`, `map`, `flatMap`, and `filter` methods which allow them to be expressed in `for` 'loops' while Scala translates them to method calls (as correctly illustrated in the code provided by the other answer by @emil-ivanov).
As with regular Scala collections, the `for` is syntactic sugar for nested method calls to `flatMap`/`map` and `filter`; unlike regular collections, the Slick `Table` objects' versions of `map` and `filter` return representations of 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 `q2` is not your usual collection (as a for comprehension in Scala is typically used to return), but rather a representation of a query. (Just as the Scala Option Monad also works with `for` comprehensions despite not being a 'collection' (in the way that `List` or `Map` is))
You can see the underlying query with `q2.selectStatement`.
Scala's implicit lifting - `c.price` is not an `Int` but rather a representation of a column value - so the expression `c.price < 9.0` becomes `c.price.<(Const(9.0))` (an `Int` is lifted to the desired type), and `<` is a just a method of the class that represents `c.price`, a `Column`. The `<` method does not do what `<` usually does (in the case of plain `Int`s) - it simply returns a representation of the SQL AST corresponding to `price < 9` that becomes part of the 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.
Problem
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?