scalaslick

How to pass a variable as part of a record deletion in scala with slick


I have a scala method for deleting a record in postGres. This uses scala-slick as well. The original implementation worked fine. Here is that implementation:

def deleteRecord(username: String, id: String, mappingRequest: MappingRequest): DBIO[Option[String]] = {
val tbl = MySchema.fullTblName(config)
val action =
  sql"""
     DELETE FROM #$tbl WHERE (#${MySchema.columns.id}) = $id
     OR (SELECT false WHERE 'xusername' = $username)
     RETURNING #${MySchema.columns.id}, $username;
   """.as[(String, String)].headOption

  action.flatMap {
    case Some((result, returnedUserId)) =>
      DBIO.successful(Some(result))
    case None =>
      DBIO.failed(new Exception("Delete failed, probably due to id not found in table"))
  }
}

However, I have a need to pass the username as part of the action, for a postGres trigger function to read the username value to add to a history table (the username is not part of the actual delete so I needed to convey it to the trigger function some other way). Here is my attempt at the implementation:

def deleteRecord(username: String, id: String, mappingRequest: MappingRequest): DBIO[Option[String]] = {
    val tbl = MySchema.fullTblName(config)
    val setSessionVariable = sqlu"SET my_variable = $username"
    val deleteAction =
      sql"""
         DELETE FROM #$tbl WHERE (#${MySchema.columns.id}) = $id
         OR (SELECT false WHERE 'xusername' = $username)
         RETURNING #${MySchema.columns.id}, $username;
       """.as[(String, String)].headOption

    for {
      _ <- setSessionVariable
      actionResult <- deleteAction
    } yield actionResult match {
      case Some((result, returnedUserId)) =>
        Some(result)
      case None =>
        throw new Exception("Delete failed, probably due to id not found in table")
    }
  }

When I execute the method, I am getting the following sql exception:

ERROR: syntax error at or near \"$1\"\n  Position: 19  Error Code: 42601"

Obviously something is wrong with the construction of this query (or double query). I tried figuring out which line this was referring to, but I am struggling to capture the logging of the generated sql statement(s) that includes the variable substitution.

I would be extremely grateful if someone can look at this code and tell me what I might be doing wrong. At the end of the day, I simply need some scala/slick implementation to pass the username as part of successfully deleting the record from the table so that it available to my trigger.

thanks for any ideas.

Update to my post: To attempt to debug my issue, I hardcoded the SET statement as follows:

val setSessionVariable = sqlu"SET my_variable = 'myUser'"

I am now getting a different error:

ERROR: unrecognized configuration parameter \"my_variable\"

Since I am trying to create a session variable, I am puzzled why postGres would say "unrecognized". Does the session variable have to exist before I assign a value to it? If so then that implies it exists outside the session (or at least that is how I am interpretting the error message). Again, any ideas or insights are greatly appreciated.


Solution

  • Ok, here is the solution. The only changes need to get the set variable query to work properly were the syntax for the scala-slick sqlu line. Here is the correct syntax:

    val setSessionVariable = sqlu"SET my.variable = '#$myUser'"