skip to Main Content

I’m trying to use a Scala 2 enum with Quill, like so:

import io.getquill.MappedEncoding

object MyEnumType extends Enumeration {
  type MyEnumType = Value

  val ONE, TWO, THREE = Value

  implicit val encode: MappedEncoding[MyEnumType, String] =
    MappedEncoding(_.toString)
  implicit val decode: MappedEncoding[String, MyEnumType] =
    MappedEncoding(MyEnumType.withName)
}

But I’m ending up with an error from Postgres:

ERROR: operator does not exist: my_enum_type = character varying
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.

I’m printing out the query using translate, and the query is generated like so:

WHERE column_1 = ONE

Where I’m expecting it to be rendered like:

WHERE column_1 = 'ONE'

What’s the proper way to handle enums with Quill in Scala 2.13?

Edit

I have been experimenting, including using the Enumeratum library, and enum values are still not being generated correctly.

Using the debugger, I can see that the custom encoder is being evaluated, but the result value never makes it to the generated query.

I have posted an example of the problem here:
https://gist.github.com/daharon/97e8b167911723054ac3845fc35c0b11

2

Answers


  1. Chosen as BEST ANSWER

    The problem was that by default the enum value was being generated as a java.sql.Types.VARCHAR by Quill. Hence the error, operator does not exist: my_enum_type = character varying, since Postgres didn't know how to convert a character varying to my custom Postgres enum type.

    The solution was to force Quill to encode the value as java.sql.Types.OTHER.

    object Ctx extends PostgresJdbcContext(SnakeCase)
    
    object MyEnumType extends Enumeration {
      type MyEnumType = Value
    
      val ONE, TWO, THREE = Value
    
      import Ctx.*
      
      implicit val enc: Encoder[MyEnumType] = encoder(
        java.sql.Types.OTHER,
        (index, value, row) => row.setObject(index, value.toString, java.sql.Types.OTHER)
      )
    
      implicit val dec: Decoder[MyEnumType] =
        decoder(row => index => this.withName(row.getObject(index).toString))
    }
    

  2. Try to add quotes

    implicit val encode: MappedEncoding[MyEnumType, String] =
      MappedEncoding(x => s"'$x'")
    implicit val decode: MappedEncoding[String, MyEnumType] =
      MappedEncoding(s => MyEnumType.withName(s.stripPrefix("'").stripSuffix("'")))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search