I am experiencing a strange behaviour with slick and I would like some help figuring out why it happens. The issue is that I have a query that reads as follows:
db.withSession { implicit session =>
tables.users.where(_.id === UserId(1)).firstOption
}
This does not compile producing an error as follows:
inferred type arguments [Boolean] do not conform to method where's type parameter bounds [T <: scala.slick.lifted.Column[_]]
But if I rewrite the code as:
db.withSession { implicit session =>
(for {
u <- tables.users if u.id === UserId(1)
} yield u).firstOption
}
It compiles and works fine.
The table is defined as follows:
class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[UserId]("id", O.PrimaryKey, O.AutoInc, O.NotNull)
}
And I have an implicit conversion to map the UserId type:
implicit lazy val userIdColumnType = MappedColumnType.base[UserId, Int](_.value, UserId(_))
It looks like a type inference problem, but I can't really understand why it should happen.
Anyone has any on why this should behave differently in the two scenario I reported?
EDIT: After some investigation I found that when using where
the implicit conversion for the userIdColumnType
has to be in scope, while with the for comprehension it is not needed. Is there a good explanation for this?
You are using === from ScalaTest. It returns a Boolean. Slick's === returns a Column[Boolean]
. The methods filter
and where
prevent using Boolean (at least in the latest version of Slick), to protect you from accidentally using ==
or also from using ScalaTest's ===
in your case, which does a local comparison of the underlying values instead of an equality comparison in the database, which is what you actualy want. For comprehensions are desugared to withFilter
and can sometimes generate a Boolean value, so unfortunately we cannot disallow Boolean
for comprehensions.
To fix this you need to make sure, that Slick's ===
is picked in queries. Maybe you can affect this with the import order or scope. Or if you are unlucky you can't and they are incompatible.
I am not sure how the userIdColumnType interacts here at the moment.