Comment Scala Slick traduit-il le code Scala en JDBC?

Comment Slick traduire le code tel que:

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)

dans JDBC?

utilise-t-il Scala virtualisé? Faut-il utiliser une autre méthode?

17
demandé sur Phil 2012-12-07 11:03:50

2 réponses

Slick API stable réalise ce par ce qu'il appelle levé l'incorporation de . Votre exemple utilise clairement L'API stable (comme vous utilisez === pour l'égalité et non == ).

la beauté de Slick (et à son tour Scala) est que - ce beaucoup est réalisé sans utiliser les macros ou Scala-virtualisé. (Note de Côté: Slick expérimental API fait de l'utilisation de macros et permettez-les d'être exprimés en for 'boucles' tandis que Scala traduit pour les appels de méthode (comme correctement illustré dans le code fourni par l'autre réponse de @emil-ivanov ).

comme pour les collections régulières de Scala, le for est du sucre syntaxique pour emboîter appels de méthode à flatMap / map et filter ; contrairement à collections régulières, les versions Slick Table des objets map et filter retour représentations d'une requête, la construire avec chaque condition de filtre ( if ) ou joindre (comme dans s <- Suppliers if s.id is c.supID )

ainsi le type de q2 n'est pas votre collection habituelle (comme pour la compréhension en Scala est généralement utilisé pour le retour), mais plutôt une représentation d'une requête. (Tout comme L'Option Scala Monad fonctionne aussi avec for malgré les interprétations de la n'étant pas une "collection" (comme List ou Map est)

Vous pouvez voir la requête sous-jacente avec q2.selectStatement .

  • l'implicite de Scala lifting - c.price n'est pas une Int mais plutôt une représentation de une valeur de colonne - ainsi l'expression c.price < 9.0 devient c.price.<(Const(9.0)) (un Int est soulevé au type désiré), et < est une méthode juste de la classe qui représente c.price , une Column . La méthode < ne fait pas ce que < fait habituellement (dans le cas de "Uni Int s) - il retourne simplement une représentation de la SQL AST correspondant à price < 9 qui fait partie le SQL qui est généré et envoyé à JDBC pour être exécuté.

  • il y a beaucoup d'autres choses qui se passent, en termes de détails, mais je pense que le interrogation monad et le levage implicite sont les ingrédients principaux.

    31
    répondu Faiz 2017-05-23 11:53:25

    en Scala, la" boucle "151920920 n'est pas en fait une construction linguistique particulière, mais plutôt un sucre syntaxique. Votre premier exemple

    val q2 = for {
      c <- Coffees if c.price < 9.0
      s <- Suppliers if s.id === c.supID
    } yield (c.name, s.name)
    

    se traduit par quelque chose dans les lignes de:

    val q2 = Coffees.withFilter(_.price < 9.0).flatMap(c =>
        Suppliers.withFilter(_.id === c.supID).map(s =>
            (c.name, s.name)
        )
    )
    

    maintenant, le flatMap , map , withFilter (et foreach ) ne filtrent pas réellement la collection, mais recueillent plutôt ce qui est hapening dans un AST (Arbre de syntaxe abstraite), qui est ensuite manipulé à Slick pour traduire en SQL.

    aussi, c.price , c.supID sont en fait lisse column s, dont < , > , === (et ainsi de suite) les méthodes ne renvoient pas bool, mais recueillent la comparaison ainsi, qui est ensuite transmis pour être converti en SQL.

    C'est un talk par les créateurs, où la plupart de ce qui est décrit (correctement).

    14
    répondu Emil Ivanov 2012-12-07 07:21:49