postgresqlscalaquill-scala

How to perform an update with optional columns using Scala quill?


I'm working on a legacy system that uses Scala Quill. I want to have a generic update function in my DAO and only update the columns that are passed. For example:

override def updateStatus(
    personId: Int,
    name: Option[String] = None,
    address: Option[String] = None): Long = ctx.run(
      query[Person]
      .filter(_.id == lift(personId))
      .update(
        p => if (name.isDefined) p.name -> lift(name.get) else p.name -> p.name,
        p => if (address.isDefined) p.address -> lift(address.get) else p.address = p.address
      )
    )

The example above, although compilable, incurs in the following runtime exception:

org.postgresql.util.PSQLException: ERROR: column "unused" of relation "person" does not exist
  Position: 99

Any suggestion?


Solution

  • Quill just translates your code to sql, so every part of code should be wrapeed in lift.

    You will see translated sql code when you compile your scala code.

    the if (name.isDefined) p.name -> lift(name.get) else p.name -> p.name cant be translated to sql.

    And your code has some typo. such as p.address = p.address

    BTW, it's not recommend to use .get in Option value. When we forget check the value, None.get will throw NoSuchElementException.

    Try this

    def updateStatus(
        personId: Int,
        name: Option[String] = None,
        address: Option[String] = None
      ) = ctx.run {
        query[Person]
          .filter(_.id == lift(personId))
          .update(
            p => p.name -> lift(name.getOrElse(p.name)),
            p => p.address -> lift(address.getOrElse(p.address))
          )
    
      }
    

    it will be translate to sql like following

    UPDATE person SET name = ?, address = ? WHERE id = ?