2014-11-21 2 views
0

У меня есть запрос в пятно, которое имеет подзапрос, глядя, как это:Slick подзапрос: Нет типа для символа не s2 найдено для реф s2

(User join Address on (_.id === _.userId)) 
.map { case (user, address) => 
    (
     user.id, 
     address.id, 
     address.street, 
     Detail.filter(_.userId === user.id).map(_.value).first 
    ) 
}.list 

, который вызывает исключение:

[SlickException: No type for symbol s2 found for Ref s2] 

Что здесь проблема? Чтобы быть ясным, это упрощенная версия моего производственного кода для удобства, однако ошибка является точно такой же.

Стек: Slick 2,1/Scala 2.11.4/Play Framework 2.3.6/Java 8

классы Таблица генерируются скользкий генератором кода (я хотел бы сохранить его таким образом):

package db 
// AUTO-GENERATED Slick data model 
/** Stand-alone Slick data model for immediate use */ 
object Tables extends { 
    val profile = scala.slick.driver.PostgresDriver 
} with Tables 

/** Slick data model trait for extension, choice of backend or usage in the cake pattern. (Make sure to initialize this late.) */ 
trait Tables { 
    val profile: scala.slick.driver.JdbcProfile 
    import profile.simple._ 
    import scala.slick.model.ForeignKeyAction 
    // NOTE: GetResult mappers for plain SQL are only generated for tables where Slick knows how to map the types of all columns. 
    import scala.slick.jdbc.{GetResult => GR} 

    /** DDL for all tables. Call .create to execute. */ 
    lazy val ddl = Address.ddl ++ Detail.ddl ++ User.ddl 

    /** Entity class storing rows of table Address 
    * @param id Database column id DBType(serial), AutoInc, PrimaryKey 
    * @param userId Database column user_id DBType(int4) 
    * @param street Database column street DBType(varchar), Length(2147483647,true) */ 
    case class AddressRow(id: Int, userId: Int, street: String) 
    /** GetResult implicit for fetching AddressRow objects using plain SQL queries */ 
    implicit def GetResultAddressRow(implicit e0: GR[Int], e1: GR[String]): GR[AddressRow] = GR{ 
    prs => import prs._ 
    AddressRow.tupled((<<[Int], <<[Int], <<[String])) 
    } 
    /** Table description of table address. Objects of this class serve as prototypes for rows in queries. */ 
    class Address(_tableTag: Tag) extends Table[AddressRow](_tableTag, "address") { 
    def * = (id, userId, street) <> (AddressRow.tupled, AddressRow.unapply) 
    /** Maps whole row to an option. Useful for outer joins. */ 
    def ? = (id.?, userId.?, street.?).shaped.<>({r=>import r._; _1.map(_=> AddressRow.tupled((_1.get, _2.get, _3.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported.")) 

    /** Database column id DBType(serial), AutoInc, PrimaryKey */ 
    val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey) 
    /** Database column user_id DBType(int4) */ 
    val userId: Column[Int] = column[Int]("user_id") 
    /** Database column street DBType(varchar), Length(2147483647,true) */ 
    val street: Column[String] = column[String]("street", O.Length(2147483647,varying=true)) 
    } 
    /** Collection-like TableQuery object for table Address */ 
    lazy val Address = new TableQuery(tag => new Address(tag)) 

    /** Entity class storing rows of table Detail 
    * @param id Database column id DBType(serial), AutoInc, PrimaryKey 
    * @param userId Database column user_id DBType(int4) 
    * @param value Database column value DBType(varchar), Length(2147483647,true) */ 
    case class DetailRow(id: Int, userId: Int, value: String) 
    /** GetResult implicit for fetching DetailRow objects using plain SQL queries */ 
    implicit def GetResultDetailRow(implicit e0: GR[Int], e1: GR[String]): GR[DetailRow] = GR{ 
    prs => import prs._ 
    DetailRow.tupled((<<[Int], <<[Int], <<[String])) 
    } 
    /** Table description of table detail. Objects of this class serve as prototypes for rows in queries. */ 
    class Detail(_tableTag: Tag) extends Table[DetailRow](_tableTag, "detail") { 
    def * = (id, userId, value) <> (DetailRow.tupled, DetailRow.unapply) 
    /** Maps whole row to an option. Useful for outer joins. */ 
    def ? = (id.?, userId.?, value.?).shaped.<>({r=>import r._; _1.map(_=> DetailRow.tupled((_1.get, _2.get, _3.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported.")) 

    /** Database column id DBType(serial), AutoInc, PrimaryKey */ 
    val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey) 
    /** Database column user_id DBType(int4) */ 
    val userId: Column[Int] = column[Int]("user_id") 
    /** Database column value DBType(varchar), Length(2147483647,true) */ 
    val value: Column[String] = column[String]("value", O.Length(2147483647,varying=true)) 
    } 
    /** Collection-like TableQuery object for table Detail */ 
    lazy val Detail = new TableQuery(tag => new Detail(tag)) 

    /** Entity class storing rows of table User 
    * @param id Database column id DBType(serial), AutoInc, PrimaryKey 
    * @param name Database column name DBType(varchar), Length(2147483647,true) */ 
    case class UserRow(id: Int, name: String) 
    /** GetResult implicit for fetching UserRow objects using plain SQL queries */ 
    implicit def GetResultUserRow(implicit e0: GR[Int], e1: GR[String]): GR[UserRow] = GR{ 
    prs => import prs._ 
    UserRow.tupled((<<[Int], <<[String])) 
    } 
    /** Table description of table user. Objects of this class serve as prototypes for rows in queries. */ 
    class User(_tableTag: Tag) extends Table[UserRow](_tableTag, "user") { 
    def * = (id, name) <> (UserRow.tupled, UserRow.unapply) 
    /** Maps whole row to an option. Useful for outer joins. */ 
    def ? = (id.?, name.?).shaped.<>({r=>import r._; _1.map(_=> UserRow.tupled((_1.get, _2.get)))}, (_:Any) => throw new Exception("Inserting into ? projection not supported.")) 

    /** Database column id DBType(serial), AutoInc, PrimaryKey */ 
    val id: Column[Int] = column[Int]("id", O.AutoInc, O.PrimaryKey) 
    /** Database column name DBType(varchar), Length(2147483647,true) */ 
    val name: Column[String] = column[String]("name", O.Length(2147483647,varying=true)) 
    } 
    /** Collection-like TableQuery object for table User */ 
    lazy val User = new TableQuery(tag => new User(tag)) 
} 

UPDATE: Я теперь понимаю, что .first подзапрос производит String, где на самом деле мне нужно, чтобы это было Column[String] что-то вроде

Detail.filter(_.userId === user.id).map(_.value).max

делает работу, но тогда подзапрос выглядит следующим образом:

SELECT MAX(value) FROM Detail WHERE userId = user.id

, когда мне это нужно, чтобы смотреть больше как это:

SELECT value FROM Detail WHERE userId = user.id LIMIT 1

ответ

0

Я думаю, что вы хотите что-то вроде этого:

val q = for { 
    ((u, a), d) <- User.innerJoin(Addres).on(_.id === _.userId) 
    .innerJoin(Detail).on(_._1.id === _.userId) 
    } yield (u, a, d.value) 

val result = q.list 
+0

Спасибо за предложение, но нет, я этого не делаю. Я упомянул, что это упрощенная версия проблемы, и она абсолютно должна быть подзапросом. – Caballero

+0

Хорошо, я думаю, что вижу вашу точку зрения. Обратите внимание, что как «первый», так и «список» являются методами «Invoker» и попадают в базу данных. Это означает, что вы не выполняете подзапрос в своем коде. – tfh

+0

Изначально я ошибочно считал, что '.irst 'фактически является функцией агрегации SQL' FIRST() '- http://www.w3schools.com/sql/sql_functions.asp – Caballero

 Смежные вопросы

  • Нет связанных вопросов^_^