¿Cómo Scala Slick traduce el código de Scala en JDBC?
(2)
En Scala, el for "loop" no es en realidad una construcción de lenguaje especial, sino azúcar sintáctica. Tu primer ejemplo
val q2 = for {
c <- Coffees if c.price < 9.0
s <- Suppliers if s.id === c.supID
} yield (c.name, s.name)
Se traduce en algo en las líneas de:
val q2 = Coffees.withFilter(_.price < 9.0).flatMap(c =>
Suppliers.withFilter(_.id === c.supID).map(s =>
(c.name, s.name)
)
)
Ahora, flatMap , map , withFilter (y foreach ) en realidad no filtran la colección, sino que recopilan lo que está sucediendo en un AST (árbol de sintaxis abstracta), que luego es manejado por Slick para traducirlo a SQL.
Además, c.price , c.supID son en realidad column Slick, cuyos métodos < , > , === (y así sucesivamente) no devuelven bool, sino que también recopilan la comparación, que luego se pasa a convertir a SQL.
Esta es una charla de los creadores, donde la mayor parte de esto se describe (correctamente).
¿Cómo traduce Slick código como:
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)
En JDBC?
¿Utiliza Scala virtualizado? ¿Utiliza algún otro método?
La API estable de Slick logra esto a través de lo que llama incrustación levantada . Su ejemplo es claramente el uso de la API estable (como usa === para la igualdad y no == ).
La belleza de Slick (y, a su vez, Scala) es que: esto se logra sin usar macros o Scala-virtualizado. (Nota: la API experimental de Slick usa macros, y esto le permitirá usar == lugar de === o is )
La traducción a SQL se realiza mediante:
La sintaxis de Scala
forcomprensión, que se traduce en llamadas de método. Las tablas definidas en Slick son Mónadas : tienen los métodos mágicos deforeach,map,flatMapyfilterque les permiten expresarse en "bucles", mientras que Scala los traduce en llamadas a métodos (como se ilustra correctamente en el código proporcionado por la otra respuesta). por @emil-ivanov ).Al igual que con las colecciones regulares de Scala, el
fores azúcar sintáctico para llamadas de método anidadas aflatMap/mapandfilter; a diferencia de las colecciones regulares, las versiones delmapy delfilterobjetos SlickTabledevuelven representaciones de una consulta, y las <- Suppliers if s.id is c.supIDjunto con cada condición de filtro (if) o unen (como ens <- Suppliers if s.id is c.supID)Por lo tanto, el tipo de
q2no es su colección habitual (como se suele utilizar para la comprensión en Scala), sino una representación de una consulta. (Del mismo modo que la Monada de opciones de Scala también funciona con comprensión a pesar de no ser una "colección" (en la forma en que es laListo elMap))Puede ver la consulta subyacente con
q2.selectStatement.El levantamiento implícito de Scala -
c.priceno es unIntsino una representación de un valor de columna - por lo que la expresiónc.price < 9.0convierte enc.price.<(Const(9.0))(unIntse levanta al tipo deseado) y<es solo un método de la clase que representac.price, unaColumn. El<método no hace lo que<normalmente hace (en el caso de losInt.Int): simplemente devuelve una representación del AST de SQL correspondiente alprice < 9que se convierte en parte del SQL que se genera y envía a JDBC para que se ejecute .
Hay muchas otras cosas más, en términos de detalles, pero creo que la mónada de la consulta y el levantamiento implícito son los principales ingredientes.