How to return full row using Slick's insertOrUpdate

Solved - posting it incase it helps anyone else trying to do something similar:

//will return the new session_id on insert, and None on update
  def save_report(report: Report): Future[Option[Long]] = {
    val insertQuery = (reportsTable returning reportsTable.map(_.session_id)).insertOrUpdate(report)
    dbConfig.db.run(insertQuery)
  }

Works well - insertOrUpdate doesn't returning anything it seems on update, so if I need to get the updated data after the update operation I can then run a subsequent query to get the information using the session id.


You cannot return whole Report, first return Id (returning(reportsTable.map(_.session_id))) and then get whole object

Check if report exists in the database if it exists update it, if not go ahead inserting the report into the database.

Note do above operations in all or none fashion by using Transactions

def getReportDBIO(id: Long): DBIO[Report] = reportsTable.filter(_.session_id === id).result.head

def save_report(report: Report): Future[Report] = {
  val query = reportsTable.filter(_.session_id === report.session_id)
  val existsAction = query.exists.result
  val insertOrUpdateAction = 
  (for { 
     exists <- existsAction
     result <- exists match {
        case true => 
        query.update(report).flatMap {_ => getReportDBIO(report.session_id)}.transactionally
        case false => {
           val insertAction = reportsTable.returning(reportsTable.map(_.session_id)) += report
           val finalAction = insertAction.flatMap( id => getReportDBIO(id)).transactionally //transactionally is important
            finalAction
        }
     }
  } yield result).transactionally

  dbConfig.db.run(insertOrUpdateAction)
}

Update your insertOrUpdate function accordingly