I have the following column in my db, thats a Boolean, but also accepts NULL, so true, false, and NULL are all valid:
def rtb = column[Option[Boolean]]("rtb")
and have the following optional input from the client that I'd like to filter on:
rtbFromClient: Option[Boolean] = ...
I have the following (based on this answer on how to do queries in slick: https://stackoverflow.com/a/40888918/5300930):
val query = userTable.
filter(row =>
if (rtbFromClient.isDefined)
row.rtb.get === rtbFromClient.get
else
LiteralColumn(true)
)
but am getting this error when the code runs:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
I thought it may be because row.rtb.get was throwing exception on call to get because the value in the db was null, so tried changing it to row.rtb.getOrElse(null) and row.rtb.getOrElse(None) but neither of these worked either)
Also tried the following:
if (rtbFromClient.isDefined) {
val query = query.filter(_.rtb.isDefined).filter(_.rtb.get === rtbFromClient.get)
}
But this also throws the same error at runtime:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
To summarise:
答案 0 :(得分:2)
Fist check if the column is null and then go ahead with another comparison. Ensure that rtbFromClient
is not an option.
val query = userTable.filter(row => !row.rtb.isEmpty &&
row.rtb === rtbFromClient)
The first condition ensures that nulls are filtered and the second condition checks the value in case the column value is not null.
In case you have optional value, then below code helps.
def query(value: Option[Boolean]) = value match {
case Some(userGivenRtbFromClient) =>
userTable.filter(row => !row.rtbFromClient.isNull &&
row.rtbFromClient === userGivenRtbFromClient)
case None => userTable.filter(row => row.rtbFromClient.isNull)
}
The Much cleaner version is here.
rtbFromClient: Option[Boolean]
rtbFromClient
User given optional value to compare with slick column.
userTable.filter(row => rtbFromClient.map(value => row.rtb === Some(value): Option[Boolean]).getOrElse(row.rtb.isEmpty))
答案 1 :(得分:2)
我有同样的问题。我的解决方案是(使用Slick 3.3.x测试):
val query = usersTable.filterOpt(rtbFromClient)(_.rtb === _)
情况1(当rtbFromClient为空时)对应以下SQL:
select * from users;
情况2(已定义rtbFromClient):
select * from users where rtb = ?;
答案 2 :(得分:0)
var query = userTable.drop(page.skip).take(page.top)
if (rtbFromClient.isDefined) {
query = query.filter(row => row.rtb.isDefined && row.rtb === rtbFromClient)
}
// More if blocks with optional filters here
...
dbProvider.db.run(query.result)
答案 3 :(得分:0)
尝试
val query = userTable.filter(row => rtbFromClient.map(x => Option(x) === row.rtb).getOrElse(row.rtb.isEmpty.?))
答案 4 :(得分:0)
我面临着同样的问题。玩了之后,我意识到可以直接通过该选项进行过滤,所以如果我们有专栏
def rtb = column[Option[Boolean]]("rtb")
我们正在尝试过滤
rtbFromClient: Option[Boolean] = ...
然后我们可以做:
val query: DBIO[Seq[TableElementType]] =
if (rtbFromClient.isDefined)
userTable.filter(_.rtb === rtbFromClient).result
else
userTable.result