Can't do the most basic query in Slick 3

2,301 views
Skip to first unread message

Josh

unread,
Mar 6, 2015, 12:40:37 PM3/6/15
to scala...@googlegroups.com
I'm trying to figure out how to run a very basic query in Slick 3.0.0.RC1:


val customers = TableQuery[Customers]
val query = customers.filter(_.customerId == 5)

Now what?

All the tutorials and documentation I've read have said to use query.result (doesn't exist) or query.run (also doesn't exist)

I've been stuck on this for a few hours now and it has given me a headache (literally).

Thanks for any help!

Josh

unread,
Mar 6, 2015, 12:54:17 PM3/6/15
to scala...@googlegroups.com
Also, I think it's a separate issue completely but this doesn't compile in my IDE:

class Customers(tag: Tag) extends Table[Customer](tag, "Customers") {
   
// columns here
   
def projection = LiftedCustomer(customerId.?, customerName)
   
override def * = projection
}


object CaseClassMappers {
 
implicit object CustomerShape extends CaseClassShape(LiftedCustomer.tupled, Customer.tupled)
}

It says the type of projection, LiftedCustomer, doesn't conform to ProvenShape[Customer] 

I'm using IntelliJ/Scala 2.11.6

I think it might just be the IDE though so maybe not a problem. Has anyone else experienced this?

sim

unread,
Mar 6, 2015, 1:01:31 PM3/6/15
to scala...@googlegroups.com
 Here is an example from my prj:

// search  a key in keys table on key_id
def findCard(cardId: String) = {
val qa: DBIO[Seq[Key]] = keys.filter(k => k.key_id === cardId).result
def res = bagira_db.run(qa)
res
}

works fine

Josh

unread,
Mar 6, 2015, 2:10:10 PM3/6/15
to scala...@googlegroups.com
Ok.. where did you get that triple equals method/operator from? It is not a recognized symbol for me

and filter returns a slick.lifted.Query:

I can't see 'result' anywhere there
Where is it coming from?

:/

Pedro Furlanetto

unread,
Mar 6, 2015, 2:47:39 PM3/6/15
to scala...@googlegroups.com
Josh, you are missing some essential imports. Like "import
scala.slick.driver.H2Driver.simple._", replace H2Driver with the one
you need.
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "Slick / ScalaQuery" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to scalaquery+...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/scalaquery/8dc6f266-9ca4-484f-961a-28af0911542b%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Josh

unread,
Mar 6, 2015, 4:38:39 PM3/6/15
to scala...@googlegroups.com
Hi Pedro,

I am importing the api like this:

import com.typesafe.slick.driver.db2.DB2Driver.api._

It says `simple` has been deprecated so I should import api instead.

sim

unread,
Mar 7, 2015, 12:28:50 AM3/7/15
to scala...@googlegroups.com
 From Slick  doc -

--
Note the use of === instead of == for comparing two values for equality. Similarly, the lifted embedding uses =!= instead of != for inequality. (The other comparison operators are the same as in Scala: <, <=, >=, >.)

--
http://slick.typesafe.com/doc/3.0.0-RC1/gettingstarted.html

Josh

unread,
Mar 7, 2015, 1:27:32 PM3/7/15
to scala...@googlegroups.com
Ok thanks, I've got it compiling now. I think I was getting confused because Intellij Scala plugin doesn't seem to recognise the result method which is somehow on the Query object, but it is in fact compiling ok :)

I'm having some trouble working with Futures though, e.g. to do an insert which returns the inserted row's autoinc id:

  1. def createUser(user: Json.User)(implicit db: Database): Future[Int] = {
  2.     val users = TableQuery[Users]
  3.     val action = (users returning users.map(_.userId)) += Models.User(None, user.name)
  4.     val x = db.run(action)
  5.     x
  6. }

This compiles fine, but I get a runtime exception when I call this method:

java.lang.ClassCastException: Cannot cast scala.concurrent.impl.Promise$DefaultPromise to java.lang.Integer

I debugged and saw that x.value is Some(Success(3))      (where 3 is the id column being returned)

Do you have any ideas what's wrong here? Sorry if it's a stupid question I'm still getting used to working with Futures

sim

unread,
Mar 7, 2015, 1:53:34 PM3/7/15
to scala...@googlegroups.com
another exapmple for insert:

// write a pass to passes table
def cdr(clId: Long,crdId: String,trmId: String) = {
val qa: DBIO[Int] = passes.map(p => p.forIns) += (clId,crdId,trmId)

Josh

unread,
Mar 7, 2015, 2:21:19 PM3/7/15
to scala...@googlegroups.com
well, my insert is working (as in, it is inserting the row) it's just I can't figure out how to return the Future[Int] that I want to return (representing the id of the row that gets inserted)
It seems the future value ends up being Some(Success(id)) 

I've been trying to figure out how to check the SQL being executed too.. but it just doesn't work like it says in the documentation: http://slick.typesafe.com/doc/3.0.0-RC1/queries.html?highlight=querying
It says to do query_action.statements to retrieve the SQL, but there is no statements method on type DBIO[...]!

Maybe I'll try the previous version of Slick and see if things are easier...

sim

unread,
Mar 7, 2015, 9:38:01 PM3/7/15
to scala...@googlegroups.com
You can do something like that:

your Future map(result => result.id match {
     case id: Int => do something
     case _ => do something })

Viktor Klang

unread,
Mar 7, 2015, 10:27:22 PM3/7/15
to scala...@googlegroups.com

Is 'x' a Future[Int] or Future [Nothing]?

(It always helps to add explicit types if your types don't add up)

--
Cheers,

——————
Viktor Klang
Chief Architect

Typesafe Inc.

Josh

unread,
Mar 8, 2015, 6:57:14 AM3/8/15
to scala...@googlegroups.com
You're right it turns out it wasn't a Future[Int]... it was a Future[Future[Int]] !
I think it's because I'm using akka's ask (? method) which itself returns a Future, then inside my database actor I am also using Slick to return a Future[Int]

So I guess it was just me using akka incorrectly, the solution was to do this:
val response = (databaseActor ? CreateUser(user))
.mapTo[Future[Int]]
.flatMap(identity)

Not sure if there's a better way as it doesn't seem very nice to return a Future[Future[Int]] but this seems to work...

Thanks for the advice 

Viktor Klang

unread,
Mar 8, 2015, 7:55:56 AM3/8/15
to scala...@googlegroups.com

What does the actor's receive method look like, I think you are missing a pipeTo

--
Cheers,

——————
Viktor Klang
Chief Architect

Typesafe Inc.

Josh

unread,
Mar 8, 2015, 8:07:30 AM3/8/15
to scala...@googlegroups.com
Hmm ok, it looks like this at the moment:


Should I be using pipeTo here? I'm not really sure why/when pipeTo should be used instead of tell.

Thanks,
Josh

Luis Ángel Vicente Sánchez

unread,
Mar 8, 2015, 8:09:47 AM3/8/15
to scala...@googlegroups.com

If the function returns a future, you should use pipeTo sender.

Viktor Klang

unread,
Mar 8, 2015, 10:21:42 AM3/8/15
to scala...@googlegroups.com

Assuming the UserDAO methods return futures:

def receive = {
    case CreateUser(user) =>
      UserDAO.createUser(user) pipeTo sender()
    case GetUserById(id) =>
      userDAO.getUserById(id) pipeTo sender()
  }

--
Cheers,

——————
Viktor Klang
Chief Architect

Typesafe Inc.

Josh

unread,
Mar 9, 2015, 7:07:41 AM3/9/15
to scala...@googlegroups.com
Thanks for the help, this works well :)

Viktor Klang

unread,
Mar 10, 2015, 2:43:43 AM3/10/15
to scala...@googlegroups.com

You're most welcome!

--
Cheers,

——————
Viktor Klang
Chief Architect

Typesafe Inc.

Josh

unread,
Mar 10, 2015, 9:39:38 AM3/10/15
to scala...@googlegroups.com
Does anyone know how to view the SQL statements being executed by Slick?

The documentation here: http://slick.typesafe.com/doc/3.0.0-RC1/queries.html?highlight=statements  says to use query_action.statements

But this doesn't compile for me:

val qa: DBIO[Seq[Models.User]] = query.result
println(qa.statements.head)

because the statements symbol is not found

Stefan Zeiger

unread,
Mar 10, 2015, 9:50:56 AM3/10/15
to scala...@googlegroups.com
On 2015-03-10 14:39, Josh wrote:
Does anyone know how to view the SQL statements being executed by Slick?

The documentation here: http://slick.typesafe.com/doc/3.0.0-RC1/queries.html?highlight=statements  says to use query_action.statements

But this doesn't compile for me:

val qa: DBIO[Seq[Models.User]] = query.result
println(qa.statements.head)

Remove the type annotation. Features like this which are not available for all DBIOActions are defined on specific subtypes (in this case, you need at least SqlAction[Seq[Models.User], NoStream, Effect.All]).


--
Stefan Zeiger
Slick Tech Lead
Typesafe - Build Reactive Apps!
Twitter: @StefanZeiger

Josh

unread,
Mar 10, 2015, 10:03:37 AM3/10/15
to scala...@googlegroups.com
Thanks! That works

I was using the type annotation because IntelliJ scala plugin doesn't seem to be able to figure out the type of query.result
and without the type annotation it makes it much more difficult to work with the query result in the IDE

Kabir Idris

unread,
Mar 10, 2015, 11:41:51 AM3/10/15
to scala...@googlegroups.com

Hi all, how do a retrieve the value from the future returned?

I know I can use the map , flatmap and for-expression  to manipulate the returned value but unfortunately, it will also return a future of either a success or failure
I want the return future to be a string or case class object
e.g I want to do something like this
val m = applicant.filter(_.id === "123").result

val query
= db.run(m) // this is a future object

val name
= query.map(_.name) //unfortunately val name is also a future and not a string

println
(name)   // will return scala.concurrent.impl.Promise$DefaultPromise@69ee8449

Matthew Ewer

unread,
Mar 18, 2016, 3:40:55 AM3/18/16
to Slick / ScalaQuery
GOOD GOLLY, FINALLY.  Finally figured out how to do what I (and you) want.  So, I understand that this is apparently bad form, breaks rules, etc.  But if you just want to get your dang data and be done, the key is basically "Await.result()".  For example:

Await.result(db.run(users.map(_.name).result), Duration.Inf)

Assuming all the code's in place to set up the users table and everything, this should give you a Seq[String] of the names of all the users.
Reply all
Reply to author
Forward
0 new messages