srvy srvy - 1 month ago 73
Scala Question

Scala/slick: Get the id of row inserted if not exists already

I am trying to insert-if-not-exists already using this piece of code

case class Item(name: String, id: Long = 0L) // name is unique

val data = Query("Bob")
val exists = items.filter(_.name === "Bob").exists
val sel = data.filterNot(_ => exists)
val action = items.map(_.name).forceInsertQuery(sel)


It works but I want to return the id of the row (existing / inserted). Currently it returns a boolean. How do I get the id without having to query again ?

Answer

If id is primary key and auto increment then you can return the id in the same insert query. if not, its not possible.

val tableQuery = TableQuery[Items] //items is a slick table

def getIdAfterInsert(item: Item): DB[Long] = {
  tableQuery.filter(_.name === item.name).take(1).result.headOption.flatMap {
    case Some(dbItem) =>
      DBIO.successful(dbItem.id)
    case None =>
     tableQuery.returning(tableQuery.map(_.id)) += item 
  }
}

But if id is not primary key and auto increment then you have to do.

def getIdAfterInsert(item: Item): DBIO[Long] = {
 tableQuery.filter(_.name === item.name).take(1).result.headOption {
  case Some(item) => DBIO.successful(item.id)
  case None => 
    (tableQuery += item).flatMap { _ => 
      tableQuery.filter(_.name === item.name).take(1).result.id //this is the extra query
    }
 }
}
Comments