2
votes

I want to do something like this (this is a made-up example to simplify my actual problem):

def findByGender(isMale: Option[Boolean]) = {
  People.filter(row => row.name.isNotNull && isMale match {
    case Some(true) => row.wife.isNotNull      // find rows where wife column is not null
    case Some(false) => row.wife.isNull        // find rows where wife column is null
    case None => true                          // select everything
  })    
}

This does not compile because of the last "true". Any better way to do this?

2

2 Answers

4
votes

You have to make it a Column[Boolean]:

def findByGender(isMale: Option[Boolean]) = {
  People.filter(row => row.name.isNotNull && isMale match {
    case Some(true) => row.wife.isNotNull      // find rows where wife column is not null
    case Some(false) => row.wife.isNull        // find rows where wife column is null
    case None => LiteralColumn(true)           // select everything
  })    
}
1
votes

If you're using Slick 3.3.x you can use the following solution:

def findByGender(isMale: Option[Boolean]) = 
  People
    .filter(_.name.isDefined)
    .filterIf(isMale == Some(true))(_.wife.isDefined)
    .filterIf(isMale == Some(false))(_.wife.isEmpty)

or

def findByGender(isMale: Option[Boolean]) = 
  People
    .filter(_.name.isDefined)
    .filterOpt(isMale) {
      case (row, true) => row.wife.isDefined
      case (row, false) => row.wife.isEmpty
    }

There are 3 cases:

  1. isMale is defined and equal Some(true)

    Result SQL: select * from people when (name is not null) and (wife is not null);

  2. isMale is defined and equal Some(false):

    Result SQL: select * from people when (name is not null) and (wife is null);

  3. isMale is empty

    Result SQL: select * from people when name is not null;