2012-12-07 20 views

risposta

31

L'API stabile di Slick raggiunge questo tramite ciò che viene chiamato incorporato in stato di espansione. Il tuo esempio usa chiaramente l'API stabile (dato che usi === per l'uguaglianza e non ==).

La bellezza di Slick (ea sua volta Scala) è questa: si ottiene questo risultato senza l'utilizzo di macro o Scala-Virtualizzato. (Nota a margine: API sperimentale di Slick fa uso di macro - e questo vi permetterà di utilizzare == invece di === o is)

La traduzione a SQL si ottiene utilizzando:

  1. Scala di for sintassi di comprensione, che viene tradotta in chiamate di metodo. tabelle definite in Slick sono Monadi - hanno la magia foreach, map, flatMap, e filter metodi che consentano loro di essere espressi in for 'loop', mentre Scala li traduce in chiamate di metodo (come illustrato in modo corretto nel codice fornito da the other answer by @emil-ivanov).

    Come con collezioni regolari Scala, il for è zucchero sintattico per il metodo annidato chiama a flatMap/map e filter; differenza collezioni regolari, versioni la chiazza di petrolio Table degli oggetti di map e filter ritorno rappresentazioni di una query, costruirlo insieme ad ogni condizione di filtro (if) o partecipare (come in s <- Suppliers if s.id is c.supID)

    Così il tipo di q2 non è la solita raccolta (come per comprensione in Scala viene in genere utilizzato per restituire), ma piuttosto una rappresentazione di una query. (Proprio come il Scala Option Monad funziona anche con for comprensioni nonostante non essendo un 'collezione' (nel modo in cui List o Map è))

    Si può vedere la domanda di fondo con q2.selectStatement.

  2. Scala di implicita sollevamento - c.price non è un Int ma piuttosto una rappresentazione di un valore di colonna - quindi l'espressione c.price < 9.0 diventa c.price.<(Const(9.0)) (a Int è sollevato al tipo desiderato), e < è solo un metodo della classe che rappresenta c.price, a Column. Il metodo < non fa ciò < solito fa (nel caso di strisciamento Int s) - restituisce semplicemente una rappresentazione della AST SQL corrispondente a price < 9 che diventa parte SQL generato e spedito a JDBC eseguire.

C'è un bel po 'che succede, in termini di dettagli, ma penso che la monade query e il sollevamento implicita sono gli ingredienti principali.

+0

Davvero un ottimo post. Il sollevamento implicito è abbastanza intelligente –

14

In Scala il "ciclo" for non è in realtà un costrutto linguaggio speciale, ma piuttosto zucchero sintattico. Il tuo primo esempio

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

si traduce in qualcosa nelle linee di:

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

Ora, il flatMap, map, withFilter (e foreach) in realtà non filtrare la raccolta, ma piuttosto di raccogliere ciò che è hapening in un AST (Abstract Syntax Tree), che viene quindi gestito da Slick per tradurre in SQL.

Inoltre, c.price, c.supID sono in realtà Slick column s, cui <, >, === (e così via) metodi non restituiscono bool, ma raccolgono il confronto pure, che viene poi passato giù da convertire SQL.

This is a talk dai creatori, dove la maggior parte di questo è descritto (correttamente).

Problemi correlati