Whilst performing a WHERE clause operation on a custom Postgres "object type" I ended up the following PSQLException.
- Language: Kotlin.
- ORM Library: Ktorm ORM.
Exception
org.postgresql.util.PSQLException: ERROR: operator does not exist: rate = character varying
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
I have followed the Ktorm official guides here but, there is no mention of custom Postgres types. Any pointers/help would be highly appreciated. See code below to reproduce:
Thank you.
- Example test that would produce the above exception
internal class SuppliersInstanceDAOTest {
@Test
fun shouldReturnInstanceSequence() {
val database = Database.connect("jdbc:postgresql://localhost:5432/mydb", user = "postgres", password = "superpassword")
val instanceDate: LocalDate = LocalDate.of(2019, 4, 1)
database.withSchemaTransaction("suppliers") {
database.from(SuppliersInstanceTable)
.select(SuppliersInstanceTable.instanceSeq)
.whereWithConditions {
// The following line causes "ERROR: operator does not exist: rate = character varying"
it += SuppliersInstanceTable.rate eq Rate.DAILY
}.asIterable()
.first()
.getInt(1)
}
}
}
- Schema
-- Note the special custom enum object type here that I cannot do anything about
CREATE TYPE suppliers.rate AS ENUM
('Daily', 'Byweekly');
CREATE TABLE suppliers.instance
(
rate suppliers.rate NOT NULL,
instance_value integer NOT NULL
)
TABLESPACE pg_default;
- Kotlin's Ktorms Entities and bindings
enum class Rate(val value: String) {
DAILY("Daily"),
BIWEEKLY("Byweekly")
}
interface SuppliersInstance : Entity<SuppliersInstance> {
companion object : Entity.Factory<SuppliersInstance>()
val rate: Rate
val instanceSeq: Int
}
object SuppliersInstanceTable : Table<SuppliersInstance>("instance") {
val rate = enum("rate", typeRef<Rate>()).primaryKey().bindTo { it.rate } // <-- Suspect
//val rate = enum<Rate>("rate", typeRef()).primaryKey().bindTo { it.rate } // Failed too
val instanceSeq = int("instance_value").primaryKey().bindTo { it.instanceSeq }
}
After seeking help from the maintainers of Ktorm, it turns out there is support in the newer version of ktorm for native Postgressql enum object types. In my case I needed
pgEnum
instead of the default ktromenum
function that converts the enums to varchar causing the clash in types in Postressql:Reference here for pgEnum
However, note at the time of writing ktorm's pgEnum function is only in ktorm v3.2.x +. The latest version available in Jcentral and mavenCentral maven repositories is v3.1.0. This is because there is also a group name change from
me.liuwj.ktorm
toorg.ktorm
in the latest version. So upgrading would also mean changing the group name in your dependencies for the new group name to match the maven repos. This was a seamless upgrade for my project and the new pgEnum worked in my use case.For my code examples above, this would mean swapping this
For