The elements type of for comprehension in ScalaQuery
I'm found something interesting when I following the Queries tutorial of ScalaQuery that I don't know why quite well.
Here is my database schema defined:
object Users extends Table[(Int, String, String)]("users") {
def id = column[Int]("id", O NotNull)
def first = column[String]("first", O NotNull)
def last = column[String]("last", O NotNull)
def * = id ~ first ~ last
}
And here is the query I use:
object Main
{
val database = Database.forURL("jdbc:sqlite:sample.db", driver = "org.sqlite.JDBC")
def main(args: Array[String]) {
database withSession {
val query1 = for (user <- Query(Users)) yield user.id ~ user.last
val query2 = for (user <- Users if user.id > 5) yield user.id ~ user ~ last
}
}
}
In this case, you could see that in both query1
and query2
use something like user.id开发者_C百科
, it seems that user
is type of singleton object Users
which I just defined above. So it has all methods defined on that object.
But if I try to run the query directly without yield
keyword, for example:
for (user <- Users if user.id > 5) {
println ("UserID:" + user.id)
}
In this case, the compiler complain:
[error] src/main/scala/Test.scala:23: value id is not a member of (Int, String, String)
[error] println ("UserID:" + user.id)
It seems like user
in the println statement is type of Tuple3. And if I use user
like ordinary tuple like the following, it will work.
for (user <- Users if user.id > 5) {
println ("UserID:" + user._1)
}
And you could see, in the guard of for expression I still use user.id
, so what is the type of user
? Why I could use user.id
in the guard and yield block, but I need use it as a tuple in the body of for expression?
Thanks.
In the first code snippet:
val query1 = for (user <- Query(Users)) yield user.id ~ user.last
user
is object Users
because the Query's map method is defined as def map[F](f: E => F): Query[F]
, the first code snippet is equals:
Query(Users).map(user => user.id ~ user.last)
so the E
is Users
's type and Users
instance is the parameter give to f(E):F
.
If you want to visit row as a Object, you need define Users as below:
import org.scalaquery.ql.basic.{BasicTable => Table}
object Users extends Table[User]("users") {
def id = column[Int]("id", O NotNull)
def first = column[String]("first", O NotNull)
def last = column[String]("last", O NotNull)
def * = id ~ first ~ last <> (User, User.unapply _)
}
case class User(id: Int, first: String, last: String)
and then
for (user <- Users if user.id > 5) {
println ("UserID:" + user.id) // user is a User instance
}
精彩评论