scala slick

¿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:

  1. La sintaxis de Scala for comprensión, que se traduce en llamadas de método. Las tablas definidas en Slick son Mónadas : tienen los métodos mágicos de foreach , map , flatMap y filter que 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 for es azúcar sintáctico para llamadas de método anidadas a flatMap / map and filter ; a diferencia de las colecciones regulares, las versiones del map y del filter objetos Slick Table devuelven representaciones de una consulta, y la s <- Suppliers if s.id is c.supID junto con cada condición de filtro ( if ) o unen (como en s <- Suppliers if s.id is c.supID )

    Por lo tanto, el tipo de q2 no 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 la List o el Map ))

    Puede ver la consulta subyacente con q2.selectStatement .

  2. El levantamiento implícito de Scala - c.price no es un Int sino una representación de un valor de columna - por lo que la expresión c.price < 9.0 convierte en c.price.<(Const(9.0)) (un Int se levanta al tipo deseado) y < es solo un método de la clase que representa c.price , una Column . El < método no hace lo que < normalmente hace (en el caso de los Int . Int ): simplemente devuelve una representación del AST de SQL correspondiente al price < 9 que 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.