0

I am trying to get an underlying querys case classes from a Scala Slick query, and it seems more difficult to me than it should be. Here is my compiler error:

[info] Compiling 18 Scala sources to /home/target/scala-2.11/classes... [error] /home/src/main/scala/com/core/address/AddressDAO.scala:30: type mismatch; [error] found : scala.slick.lifted.Query[com.core.address.AddressDAO,com.core.protocol.Address,Seq] [error] required: Option[com.core.protocol.Address] [error] q

Here is the method I have written:

  def getAddress(otherAddress: String): Future[Option[Address]] = {
    future {
      val q = for (addr <- addresses if (addr.address == otherAddress)) yield addr
      q
    }

Here is the Slick Schema:

class AddressDAO(tag: Tag) extends Table[Address](tag, "ADDRESSES") with DbConfig {

  def address = column[String]("ADDRESS", O.PrimaryKey)
  def hash160 = column[String]("HASH160")
  def n_tx = column[Long]("N_TX")
  def total_received = column[Double]("TOTAL_RECEIVED")
  def total_sent = column[Double]("TOTAL_SENT")
  def final_balance = column[Double]("FINAL_BALANCE")
  def * = (hash160, address, n_tx, total_received, total_sent, final_balance) <> (Address.tupled, Address.unapply)

}

What I want to do is expressed in the return type of the method getAddress which is Future[Option[Address]]. I want the first element that the database is finding. The type that is actually being returned is of type scala.slick.lifted.Query[com.core.address.AddressDAO,com.core.protocol.Address,Seq]

There does not seem to be any execute method or anything to kick start the query. I suspect this can be done with for-comprehensions but I cannot figure how to actually do it.

Thanks!

Chris Stewart
  • 1,641
  • 2
  • 28
  • 60

2 Answers2

1

You have to actually run your query.

q.firstOption is what you probably want to use:

def getAddress(otherAddress: String): Future[Option[Address]] = {
    future {
      val q = for (addr <- addresses if (addr.address == otherAddress)) yield addr
      q.firstOption
    }

PS. Simply filtering addresses for the given value of address is indeed more concise. And of course the performance of this query depends on whether you have an index on that field and the size of your table :)

Ashalynd
  • 12,363
  • 2
  • 34
  • 37
1

I am certainly no Slick expert, but after a quick perusal of the docs, I am wondering if maybe wrapping something like this in your Future would work:

addresses.filter(_.address === "givenAddressString").firstOption
Vidya
  • 29,932
  • 7
  • 42
  • 70
  • Not found underneath this doc? http://slick.typesafe.com/doc/2.0.0-M3/api/index.html#scala.slick.lifted.Query – Chris Stewart Nov 27 '14 at 17:07
  • For one thing, I think that's outdated since 2.0.0 is no longer a milestone and is actually a thing. But you should also look at [Invoker](http://slick.typesafe.com/doc/2.0.0/api/#scala.slick.jdbc.Invoker). As the docs say, "Queries are executed using methods defined in the Invoker trait (or UnitInvoker for the parameterless versions). There is an implicit conversion from Query, so you can execute any Query directly." – Vidya Nov 27 '14 at 17:14
  • Thank you, that was my disconnect :) – Chris Stewart Nov 27 '14 at 17:16
  • Glad to help. Good luck with your project! – Vidya Nov 27 '14 at 17:17