Skip to content

Commit

Permalink
Replace use of ResultSet in IColumnType.readObject() with common Resu…
Browse files Browse the repository at this point in the history
…ltApi

- Introduce ResultApi interface that wraps actual database result
- Introduce JdbcResult and R2dbcResult
- Since only getting object by index and/or type is supported by R2DBC, all uses
of ResultSet specific getType() functions in source code have been replaced by
getObject()
  • Loading branch information
bog-walk committed Sep 30, 2024
1 parent f576c1b commit 49fd89f
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 71 deletions.
34 changes: 22 additions & 12 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public final class org/jetbrains/exposed/sql/ArrayColumnType : org/jetbrains/exp
public fun nonNullValueToString (Ljava/util/List;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/util/List;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun setParameter (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
Expand All @@ -237,7 +237,7 @@ public final class org/jetbrains/exposed/sql/AutoIncColumnType : org/jetbrains/e
public fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun parameterMarker (Ljava/lang/Object;)Ljava/lang/String;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun setNullable (Z)V
public fun setParameter (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public fun sqlType ()Ljava/lang/String;
Expand All @@ -259,7 +259,6 @@ public class org/jetbrains/exposed/sql/BasicBinaryColumnType : org/jetbrains/exp
public fun <init> ()V
public synthetic fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public fun nonNullValueToString ([B)Ljava/lang/String;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)[B
Expand Down Expand Up @@ -302,8 +301,7 @@ public final class org/jetbrains/exposed/sql/BlobColumnType : org/jetbrains/expo
public final fun getUseObjectIdentifier ()Z
public synthetic fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public fun nonNullValueToString (Lorg/jetbrains/exposed/sql/statements/api/ExposedBlob;)Ljava/lang/String;
public synthetic fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Lorg/jetbrains/exposed/sql/statements/api/ExposedBlob;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun setParameter (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
Expand Down Expand Up @@ -514,7 +512,7 @@ public abstract class org/jetbrains/exposed/sql/ColumnType : org/jetbrains/expos
public fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun parameterMarker (Ljava/lang/Object;)Ljava/lang/String;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun setNullable (Z)V
public fun setParameter (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public fun toString ()Ljava/lang/String;
Expand Down Expand Up @@ -778,7 +776,6 @@ public final class org/jetbrains/exposed/sql/DecimalColumnType : org/jetbrains/e
public final fun getPrecision ()I
public final fun getScale ()I
public fun hashCode ()I
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/math/BigDecimal;
Expand Down Expand Up @@ -837,7 +834,7 @@ public final class org/jetbrains/exposed/sql/EntityIDColumnType : org/jetbrains/
public fun nonNullValueToString (Lorg/jetbrains/exposed/dao/id/EntityID;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Lorg/jetbrains/exposed/dao/id/EntityID;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Lorg/jetbrains/exposed/dao/id/EntityID;
Expand Down Expand Up @@ -1046,7 +1043,7 @@ public abstract interface class org/jetbrains/exposed/sql/IColumnType {
public abstract fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public abstract fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public abstract fun parameterMarker (Ljava/lang/Object;)Ljava/lang/String;
public abstract fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public abstract fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public abstract fun setNullable (Z)V
public abstract fun setParameter (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public abstract fun sqlType ()Ljava/lang/String;
Expand All @@ -1062,7 +1059,7 @@ public final class org/jetbrains/exposed/sql/IColumnType$DefaultImpls {
public static fun nonNullValueToString (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/lang/Object;)Ljava/lang/String;
public static fun notNullValueToDB (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/lang/Object;)Ljava/lang/Object;
public static fun parameterMarker (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/lang/Object;)Ljava/lang/String;
public static fun readObject (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/sql/ResultSet;I)Ljava/lang/Object;
public static fun readObject (Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public static fun setParameter (Lorg/jetbrains/exposed/sql/IColumnType;Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;ILjava/lang/Object;)V
public static fun validateValueBeforeUpdate (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/lang/Object;)V
public static fun valueAsDefaultString (Lorg/jetbrains/exposed/sql/IColumnType;Ljava/lang/Object;)Ljava/lang/String;
Expand Down Expand Up @@ -2612,7 +2609,7 @@ public class org/jetbrains/exposed/sql/TextColumnType : org/jetbrains/exposed/sq
public synthetic fun <init> (Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getEagerLoading ()Z
public fun preciseType ()Ljava/lang/String;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
}

Expand Down Expand Up @@ -2728,7 +2725,6 @@ public final class org/jetbrains/exposed/sql/UUIDColumnType : org/jetbrains/expo
public fun nonNullValueToString (Ljava/util/UUID;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/util/UUID;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/util/UUID;
Expand Down Expand Up @@ -3608,6 +3604,14 @@ protected final class org/jetbrains/exposed/sql/statements/api/IdentifierManager
public static fun values ()[Lorg/jetbrains/exposed/sql/statements/api/IdentifierManagerApi$OracleVersion;
}

public final class org/jetbrains/exposed/sql/statements/api/JdbcResult : org/jetbrains/exposed/sql/statements/api/ResultApi {
public fun <init> (Ljava/sql/ResultSet;)V
public fun getObject (I)Ljava/lang/Object;
public fun getObject (ILjava/lang/Class;)Ljava/lang/Object;
public synthetic fun getResult ()Ljava/lang/Object;
public fun getResult ()Ljava/sql/ResultSet;
}

public abstract interface class org/jetbrains/exposed/sql/statements/api/PreparedStatementApi {
public abstract fun addBatch ()V
public abstract fun cancel ()V
Expand All @@ -3632,6 +3636,12 @@ public final class org/jetbrains/exposed/sql/statements/api/PreparedStatementApi
public static fun fillParameters (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;Ljava/lang/Iterable;)I
}

public abstract interface class org/jetbrains/exposed/sql/statements/api/ResultApi {
public abstract fun getObject (I)Ljava/lang/Object;
public abstract fun getObject (ILjava/lang/Class;)Ljava/lang/Object;
public abstract fun getResult ()Ljava/lang/Object;
}

public final class org/jetbrains/exposed/sql/transactions/ThreadLocalTransactionManager : org/jetbrains/exposed/sql/transactions/TransactionManager {
public fun <init> (Lorg/jetbrains/exposed/sql/Database;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Lorg/jetbrains/exposed/sql/Database;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.jetbrains.exposed.dao.id.EntityIDFunctionProvider
import org.jetbrains.exposed.dao.id.IdTable
import org.jetbrains.exposed.sql.statements.api.ExposedBlob
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
import org.jetbrains.exposed.sql.statements.api.ResultApi
import org.jetbrains.exposed.sql.vendors.*
import java.io.InputStream
import java.math.BigDecimal
Expand All @@ -14,7 +15,6 @@ import java.math.RoundingMode
import java.nio.ByteBuffer
import java.sql.Blob
import java.sql.Clob
import java.sql.ResultSet
import java.sql.SQLException
import java.util.*
import kotlin.reflect.KClass
Expand Down Expand Up @@ -82,7 +82,7 @@ interface IColumnType<T> {
fun nonNullValueAsDefaultString(value: T & Any): String = nonNullValueToString(value)

/** Returns the object at the specified [index] in the [rs]. */
fun readObject(rs: ResultSet, index: Int): Any? = rs.getObject(index)
fun readObject(rs: ResultApi, index: Int): Any? = rs.getObject(index)

/** Sets the [value] at the specified [index] into the [stmt]. */
fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
Expand Down Expand Up @@ -259,7 +259,7 @@ class EntityIDColumnType<T : Comparable<T>>(
idColumn.table as IdTable<T>
)

override fun readObject(rs: ResultSet, index: Int): Any? = idColumn.columnType.readObject(rs, index)
override fun readObject(rs: ResultApi, index: Int): Any? = idColumn.columnType.readObject(rs, index)

override fun equals(other: Any?): Boolean {
if (other !is EntityIDColumnType<*>) return false
Expand Down Expand Up @@ -639,10 +639,6 @@ class DecimalColumnType(
) : ColumnType<BigDecimal>() {
override fun sqlType(): String = "DECIMAL($precision, $scale)"

override fun readObject(rs: ResultSet, index: Int): Any? {
return rs.getObject(index)
}

override fun valueFromDB(value: Any): BigDecimal = when (value) {
is BigDecimal -> value
is Double -> {
Expand Down Expand Up @@ -869,7 +865,7 @@ open class TextColumnType(
}
}

override fun readObject(rs: ResultSet, index: Int): Any? {
override fun readObject(rs: ResultApi, index: Int): Any? {
val value = super.readObject(rs, index)
return if (eagerLoading && value != null) {
valueFromDB(value)
Expand Down Expand Up @@ -901,12 +897,11 @@ open class LargeTextColumnType(
open class BasicBinaryColumnType : ColumnType<ByteArray>() {
override fun sqlType(): String = currentDialect.dataTypeProvider.binaryType()

override fun readObject(rs: ResultSet, index: Int): Any? = rs.getBytes(index)

override fun valueFromDB(value: Any): ByteArray = when (value) {
is Blob -> value.binaryStream.use { it.readBytes() }
is InputStream -> value.use { it.readBytes() }
is ByteArray -> value
is String -> value.toByteArray()
else -> error("Unexpected value $value of type ${value::class.qualifiedName}")
}

Expand Down Expand Up @@ -971,10 +966,11 @@ class BlobColumnType(

override fun nonNullValueToString(value: ExposedBlob): String = currentDialect.dataTypeProvider.hexToDb(value.hexString())

override fun readObject(rs: ResultSet, index: Int) = when {
currentDialect is SQLServerDialect -> rs.getBytes(index)?.let(::ExposedBlob)
currentDialect is PostgreSQLDialect && useObjectIdentifier -> rs.getBlob(index)?.binaryStream?.let(::ExposedBlob)
else -> rs.getBinaryStream(index)?.let(::ExposedBlob)
override fun readObject(rs: ResultApi, index: Int) = when {
currentDialect is PostgreSQLDialect && useObjectIdentifier -> {
rs.getObject(index, java.sql.Blob::class.java)?.binaryStream?.let(::ExposedBlob)
}
else -> rs.getObject(index)
}

override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
Expand Down Expand Up @@ -1004,11 +1000,6 @@ class UUIDColumnType : ColumnType<UUID>() {

override fun nonNullValueToString(value: UUID): String = "'$value'"

override fun readObject(rs: ResultSet, index: Int): Any? = when (currentDialect) {
is MariaDBDialect -> rs.getBytes(index)
else -> super.readObject(rs, index)
}

companion object {
private val uuidRegexp =
Regex("[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}", RegexOption.IGNORE_CASE)
Expand Down Expand Up @@ -1228,7 +1219,7 @@ class ArrayColumnType<E>(
return value.joinToString(",", prefix, "]") { delegate.valueAsDefaultString(it) }
}

override fun readObject(rs: ResultSet, index: Int): Any? = rs.getArray(index)
override fun readObject(rs: ResultApi, index: Int): Any? = rs.getObject(index, java.sql.Array::class.java)

override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) {
when {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.jetbrains.exposed.dao.id.CompositeID
import org.jetbrains.exposed.dao.id.CompositeIdTable
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.statements.api.DatabaseApi
import org.jetbrains.exposed.sql.statements.api.JdbcResult
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.withDialect
import java.sql.ResultSet
Expand Down Expand Up @@ -141,7 +142,7 @@ class ResultRow(
fieldsIndex.forEach { (field, index) ->
val columnType = (field as? ExpressionWithColumnType)?.columnType
val value = if (columnType != null) {
columnType.readObject(rs, index + 1)
columnType.readObject(JdbcResult(rs), index + 1)
} else {
rs.getObject(index + 1)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.exposed.sql.statements

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.api.JdbcResult
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.*
Expand Down Expand Up @@ -71,7 +72,7 @@ open class InsertStatement<Key : Any>(
while (rs?.next() == true) {
try {
val returnedValues = returnedColumns.associateTo(mutableMapOf()) {
it.first to it.first.columnType.readObject(rs, it.second)
it.first to it.first.columnType.readObject(JdbcResult(rs), it.second)
}
if (returnedValues.isEmpty() && firstAutoIncColumn != null) {
returnedValues[firstAutoIncColumn] = rs.getObject(1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.jetbrains.exposed.sql.statements.api

import java.sql.ResultSet

/** Base class for wrapping data generated by executing a statement that queries the database. */
interface ResultApi {
/** The actual data object returned by the database after statement execution. */
val result: Any

/**
* Returns the value of the column, at the specified [index], from the [result] object.
* using the database's default type mapping.
*/
fun getObject(index: Int): Any?

/**
* Returns the value of the column, at the specified [index], from the [result] object,
* converted from the column SQL type to the specified data [type].
*/
fun <T> getObject(index: Int, type: Class<T>): T?
}

/** Class for wrapping a [java.sql.ResultSet] generated by executing a statement that queries a JDBC database. */
class JdbcResult(
/** The actual [ResultSet] returned by the database after statement execution. */
override val result: ResultSet
) : ResultApi {
override fun getObject(index: Int): Any? = result.getObject(index)

override fun <T> getObject(index: Int, type: Class<T>): T? = result.getObject(index, type)
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ interface TransactionManager {
/**
* The database to use by default in all transactions.
*
* **Note** If this value is not set, the last [Database] instance created will be used.
* **Note** If this value is not set, the last database instance created will be used.
*/
@Suppress("SpacingBetweenDeclarationsWithAnnotations")
var defaultDatabase: DatabaseApi?
Expand Down Expand Up @@ -252,7 +252,7 @@ internal inline fun TransactionInterface.closeLoggingException(log: (Exception)
}

/**
* The [TransactionManager] instance that is associated with this [Database].
* The [TransactionManager] instance that is associated with this database.
*
* @throws [RuntimeException] If a manager has not been registered for the database.
*/
Expand Down
7 changes: 3 additions & 4 deletions exposed-java-time/api/exposed-java-time.api
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ public final class org/jetbrains/exposed/sql/javatime/JavaDurationColumnType : o
public fun nonNullValueToString (Ljava/time/Duration;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/time/Duration;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/time/Duration;
Expand All @@ -102,7 +101,7 @@ public final class org/jetbrains/exposed/sql/javatime/JavaInstantColumnType : or
public fun nonNullValueToString (Ljava/time/Instant;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/time/Instant;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/time/Instant;
Expand Down Expand Up @@ -139,7 +138,7 @@ public final class org/jetbrains/exposed/sql/javatime/JavaLocalDateTimeColumnTyp
public fun nonNullValueToString (Ljava/time/LocalDateTime;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/time/LocalDateTime;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/time/LocalDateTime;
Expand Down Expand Up @@ -176,7 +175,7 @@ public final class org/jetbrains/exposed/sql/javatime/JavaOffsetDateTimeColumnTy
public fun nonNullValueToString (Ljava/time/OffsetDateTime;)Ljava/lang/String;
public synthetic fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun notNullValueToDB (Ljava/time/OffsetDateTime;)Ljava/lang/Object;
public fun readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object;
public fun readObject (Lorg/jetbrains/exposed/sql/statements/api/ResultApi;I)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
public synthetic fun valueFromDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun valueFromDB (Ljava/lang/Object;)Ljava/time/OffsetDateTime;
Expand Down
Loading

0 comments on commit 49fd89f

Please sign in to comment.