Karl Azzam
04/09/2024, 4:30 PMKarl Azzam
04/09/2024, 6:17 PMERROR: column \"path\" is of type FooTable.ltree but expression is of type character varying\n Hint: You will need to rewrite or cast the expression.\
class LTreeType : ColumnType() {
override fun sqlType(): String = "LTREE"
}
fun Table.ltree(name: String): Column<String> = registerColumn(name, LTreeType())
object FooTable : UUIDTable("foo_table") {
val name = text("name")
val path = ltree("path")
}
FooTable.insert {
it[name] = "Bar"
it[path] = "1"
}
Chantal Loncle
04/09/2024, 11:39 PMPGobject
needs to be provided to properly describe the JDBC unknown type when setting the object in any prepared statement:
class LTreeType : StringColumnType() {
override fun sqlType(): String = "LTREE"
override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
val parameterValue: PGobject? = value?.let {
PGobject().apply {
type = sqlType()
this.value = value as? String
}
}
super.setParameter(stmt, index, parameterValue)
}
}
Tested this class with some custom operators and it produces expected results for the basic example in the above-linked reference docs.Karl Azzam
04/10/2024, 1:44 PMWARN [io.agr.pool] (DefaultDispatcher-worker-1) Datasource '<default>': JDBC resources leaked: 1 ResultSet(s) and 0 Statement(s)
i am also doing the insert in a transaction block like always, here's my loggedTransaction (using suspend/coroutines). This should in theory close out all prepared statements and result sets under the hood.
suspend fun <T> loggedTransaction(statement: Transaction.() -> T): T {
return suspendedTransactionAsync(Dispatchers.IO) {
addLogger(StdOutSqlLogger)
statement()
}.await()
}
and here's an example write:
suspend fun exampleInsert(): Result<Unit> {
return try {
loggedTransaction {
FooTable.insert {
it[name] = "Bar"
it[path] = "1"
}
}
Result.success(Unit)
} catch (ex: ExposedSQLException) {
Log.error(ex)
Result.failure(ex)
}
}
Chantal Loncle
04/10/2024, 1:47 PMKarl Azzam
04/10/2024, 1:50 PMKarl Azzam
04/10/2024, 1:51 PMKarl Azzam
04/10/2024, 1:56 PMKarl Azzam
04/10/2024, 1:56 PMKarl Azzam
04/10/2024, 2:46 PMclass org.postgresql.util.PGobject cannot be cast to class java.lang.String (org.postgresql.util.PGobject is in unnamed module of loader 'app'; java.lang.String is in module java.base of loader 'bootstrap')"
Karl Azzam
04/10/2024, 2:51 PMoverride fun valueFromDB(value: Any): Any {
val parameterValue: PGobject =
PGobject().apply {
type = sqlType()
this.value = value as? String
}
return when (value) {
is String -> parameterValue
else -> value.toString()
}
}