From 109fb79816d7992f7e284acde6738dde04d43e62 Mon Sep 17 00:00:00 2001 From: oshai Date: Mon, 4 Sep 2023 02:28:12 +0300 Subject: [PATCH 1/8] r2dbc: parse duration when string option Fix issue #412 --- .../main/java/MysqlConnectionFactoryProvider.kt | 16 ++++++++++++++-- .../mysql/MysqlConnectionFactoryProviderTest.kt | 12 ++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt b/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt index 38ea337c..67f3a07f 100644 --- a/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt +++ b/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt @@ -77,8 +77,8 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider { password = connectionFactoryOptions.getValue(PASSWORD)?.toString(), database = connectionFactoryOptions.getValue(DATABASE) as String?, applicationName = connectionFactoryOptions.getValue(APPLICATION_NAME) as String?, - connectionTimeout = (connectionFactoryOptions.getValue(CONNECT_TIMEOUT) as Duration?)?.toMillis()?.toInt() ?: 5000, - queryTimeout = connectionFactoryOptions.getValue(STATEMENT_TIMEOUT) as Duration?, + connectionTimeout = connectionFactoryOptions.getValue(CONNECT_TIMEOUT)?.parseDuration()?.toMillis()?.toInt() ?: 5000, + queryTimeout = connectionFactoryOptions.getValue(STATEMENT_TIMEOUT)?.parseDuration(), ssl = MysqlSSLConfigurationFactory.create(connectionFactoryOptions), rsaPublicKey = (connectionFactoryOptions.getValue(SERVER_RSA_PUBLIC_KEY_FILE) as String?)?.let { Paths.get(it) } ) @@ -97,3 +97,15 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider { override fun getDriver(): String = MYSQL_DRIVER } + +private fun Any.parseDuration(): Duration { + return when (this) { + is Duration -> { + this + } + is String -> { + Duration.parse(this) + } + else -> throw Exception("cant parse $this to Duration") + } +} diff --git a/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/MysqlConnectionFactoryProviderTest.kt b/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/MysqlConnectionFactoryProviderTest.kt index 24edfcf5..63753f6a 100644 --- a/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/MysqlConnectionFactoryProviderTest.kt +++ b/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/MysqlConnectionFactoryProviderTest.kt @@ -4,6 +4,7 @@ import com.github.jasync.sql.db.SSLConfiguration import io.r2dbc.spi.ConnectionFactoryOptions import org.junit.Assert.assertEquals import org.junit.Test +import java.time.Duration class MysqlConnectionFactoryProviderTest { @@ -63,4 +64,15 @@ class MysqlConnectionFactoryProviderTest { // then assertEquals("rsa.pem", result.mySQLConnectionFactory.configuration.rsaPublicKey.toString()) } + + @Test + fun shouldUseTimeoutAsString() { + val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host/db?connectTimeout=PT3S") + + // when + val result = provider.create(options) + + // then + assertEquals(Duration.parse("PT3S").toMillis().toInt(), result.mySQLConnectionFactory.configuration.connectionTimeout) + } } From 3d899dd91a04298f72971b351ed7270dd979f532 Mon Sep 17 00:00:00 2001 From: oshai Date: Mon, 4 Sep 2023 02:11:01 +0300 Subject: [PATCH 2/8] r2dbc: don't change autocommit state when starting a transaction Fix issue #413 --- r2dbc-mysql/src/main/java/JasyncClientConnection.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/r2dbc-mysql/src/main/java/JasyncClientConnection.kt b/r2dbc-mysql/src/main/java/JasyncClientConnection.kt index 456d6d99..901821e5 100644 --- a/r2dbc-mysql/src/main/java/JasyncClientConnection.kt +++ b/r2dbc-mysql/src/main/java/JasyncClientConnection.kt @@ -43,8 +43,6 @@ class JasyncClientConnection( override fun beginTransaction(definition: TransactionDefinition): Publisher { return Mono.defer { - val setAutoCommit = Mono.from(setAutoCommit(false)) - val setLockWaitTimeout = Mono.justOrEmpty(definition.getAttribute(TransactionDefinition.LOCK_WAIT_TIMEOUT)) .flatMap { timeout -> Mono.from(setLockWaitTimeout(timeout)) } @@ -53,8 +51,7 @@ class JasyncClientConnection( val startTransaction = Mono.from(beginTransaction()) - return@defer Mono.from(setAutoCommit) - .then(setLockWaitTimeout) + return@defer Mono.from(setLockWaitTimeout) .then(changeIsolationLevel) .then(startTransaction) .then() From 06bedd16d37c0e606c6da6ebfed45a87eb7084aa Mon Sep 17 00:00:00 2001 From: oshai Date: Tue, 5 Sep 2023 00:03:02 +0300 Subject: [PATCH 3/8] bump version to 2.2.5 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index eba2e35a..19635393 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,7 @@ apply(plugin = "io.github.gradle-nexus.publish-plugin") allprojects { group = "com.github.jasync-sql" - version = "2.2.4" + version = "2.2.5" apply(plugin = "kotlin") apply(plugin = "maven-publish") From 83029e5d8c7405b87c15376383afe5d8fecf9e06 Mon Sep 17 00:00:00 2001 From: Kenneth Tiller Date: Thu, 9 Nov 2023 00:37:18 +0100 Subject: [PATCH 4/8] Add query to InsufficientParametersException (#418) * added query to InsufficientParametersException * added assertions for message to existing tests --------- Co-authored-by: kenneth-tiller --- .../sql/db/exceptions/InsufficientParametersException.kt | 7 ++++--- .../java/com/github/jasync/sql/db/mysql/MySQLConnection.kt | 2 +- .../test/java/com/github/jasync/sql/db/mysql/QuerySpec.kt | 5 +++-- .../src/test/java/com/github/jasync/sql/db/mysql/Utils.kt | 2 ++ .../jasync/sql/db/postgresql/PostgreSQLConnection.kt | 2 +- .../src/test/java/com/github/aysnc/sql/db/Utils.kt | 2 ++ .../aysnc/sql/db/integration/PreparedStatementSpec.kt | 7 ++++--- 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/db-async-common/src/main/java/com/github/jasync/sql/db/exceptions/InsufficientParametersException.kt b/db-async-common/src/main/java/com/github/jasync/sql/db/exceptions/InsufficientParametersException.kt index ea290f1e..5acb9370 100644 --- a/db-async-common/src/main/java/com/github/jasync/sql/db/exceptions/InsufficientParametersException.kt +++ b/db-async-common/src/main/java/com/github/jasync/sql/db/exceptions/InsufficientParametersException.kt @@ -10,10 +10,11 @@ package com.github.jasync.sql.db.exceptions * @param given the collection given */ @Suppress("RedundantVisibilityModifier") -public class InsufficientParametersException(expected: Int, given: List) : DatabaseException( - "The query contains %s parameters but you gave it %s (%s)".format( +public class InsufficientParametersException(query: String, expected: Int, given: List) : DatabaseException( + "The query contains %s parameters but you gave it %s (%s):${System.lineSeparator()}%s".format( expected, given.size, - given.joinToString(",") + given.joinToString(","), + query ) ) diff --git a/mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt b/mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt index cae6ca6c..2591acf1 100644 --- a/mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt +++ b/mysql-async/src/main/java/com/github/jasync/sql/db/mysql/MySQLConnection.kt @@ -468,7 +468,7 @@ class MySQLConnection @JvmOverloads constructor( this.validateIsReadyForQuery() val totalParameters = params.query.count { it == '?' } if (params.values.length != totalParameters) { - throw InsufficientParametersException(totalParameters, params.values) + throw InsufficientParametersException(params.query, totalParameters, params.values) } val promise = CompletableFuture() this.setQueryPromise(promise) diff --git a/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/QuerySpec.kt b/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/QuerySpec.kt index fe88a836..34c40f47 100644 --- a/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/QuerySpec.kt +++ b/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/QuerySpec.kt @@ -239,10 +239,11 @@ class QuerySpec : ConnectionHelper() { @Test fun `connection should fail if number of args required is different than the number of provided parameters`() { withConnection { connection -> - verifyException(InsufficientParametersException::class.java) { + val query = "select * from some_table where c = ? and b = ?" + verifyException(InsufficientParametersException::class.java, containedInMessage = query) { executePreparedStatement( connection, - "select * from some_table where c = ? and b = ?", + query, listOf("one", "two", "three") ) } diff --git a/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/Utils.kt b/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/Utils.kt index a24a4ed5..2e991788 100644 --- a/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/Utils.kt +++ b/mysql-async/src/test/java/com/github/jasync/sql/db/mysql/Utils.kt @@ -5,6 +5,7 @@ import org.assertj.core.api.Assertions fun verifyException( exType: Class, causeType: Class? = null, + containedInMessage: String? = null, body: () -> Unit ): Throwable { try { @@ -13,6 +14,7 @@ fun verifyException( } catch (e: Exception) { // e.printStackTrace() Assertions.assertThat(e::class.java).isEqualTo(exType) + containedInMessage?.let { Assertions.assertThat(e.message).contains(it) } causeType?.let { Assertions.assertThat(e.cause!!::class.java).isEqualTo(it) } return e.cause ?: e } diff --git a/postgresql-async/src/main/java/com/github/jasync/sql/db/postgresql/PostgreSQLConnection.kt b/postgresql-async/src/main/java/com/github/jasync/sql/db/postgresql/PostgreSQLConnection.kt index 81ba5e56..b7145eb6 100644 --- a/postgresql-async/src/main/java/com/github/jasync/sql/db/postgresql/PostgreSQLConnection.kt +++ b/postgresql-async/src/main/java/com/github/jasync/sql/db/postgresql/PostgreSQLConnection.kt @@ -190,7 +190,7 @@ class PostgreSQLConnection @JvmOverloads constructor( if (holder.paramsCount != params.values.length) { this.clearQueryPromise() - throw InsufficientParametersException(holder.paramsCount, params.values) + throw InsufficientParametersException(params.query, holder.paramsCount, params.values) } this.currentPreparedStatement = Optional.of(holder) diff --git a/postgresql-async/src/test/java/com/github/aysnc/sql/db/Utils.kt b/postgresql-async/src/test/java/com/github/aysnc/sql/db/Utils.kt index bc7d16d6..cafea1ba 100644 --- a/postgresql-async/src/test/java/com/github/aysnc/sql/db/Utils.kt +++ b/postgresql-async/src/test/java/com/github/aysnc/sql/db/Utils.kt @@ -5,6 +5,7 @@ import org.assertj.core.api.Assertions fun verifyException( exType: Class, causeType: Class? = null, + containedInMessage: String? = null, body: () -> Unit ): Throwable { try { @@ -12,6 +13,7 @@ fun verifyException( throw Exception("Expected exception was not thrown: ${exType.simpleName}->${causeType?.simpleName}") } catch (e: Exception) { Assertions.assertThat(e::class.java).isEqualTo(exType) + containedInMessage?.let { Assertions.assertThat(e.message).contains(it) } causeType?.let { Assertions.assertThat(e.cause!!::class.java).isEqualTo(it) } return e.cause ?: e } diff --git a/postgresql-async/src/test/java/com/github/aysnc/sql/db/integration/PreparedStatementSpec.kt b/postgresql-async/src/test/java/com/github/aysnc/sql/db/integration/PreparedStatementSpec.kt index 97339a07..051b6933 100644 --- a/postgresql-async/src/test/java/com/github/aysnc/sql/db/integration/PreparedStatementSpec.kt +++ b/postgresql-async/src/test/java/com/github/aysnc/sql/db/integration/PreparedStatementSpec.kt @@ -77,7 +77,7 @@ class PreparedStatementSpec : DatabaseTestHelper() { fun `prepared statements should raise an exception if the parameter count is different from the given parameters count`() { withHandler { handler -> executeDdl(handler, this.messagesCreate) - verifyException(InsufficientParametersException::class.java) { + verifyException(InsufficientParametersException::class.java, containedInMessage = this.messagesSelectOne) { executePreparedStatement(handler, this.messagesSelectOne) } } @@ -268,9 +268,10 @@ class PreparedStatementSpec : DatabaseTestHelper() { fun `prepared statements should fail if prepared statement has more variables than it was given`() { withHandler { handler -> executeDdl(handler, messagesCreate) - verifyException(InsufficientParametersException::class.java) { + val query = "SELECT * FROM messages WHERE content = ? AND moment = ?" + verifyException(InsufficientParametersException::class.java, containedInMessage = query) { handler.sendPreparedStatement( - "SELECT * FROM messages WHERE content = ? AND moment = ?", + query, listOf("some content") ) } From a92229e5fb6b0f4786ffcde25724510b9c14f4ce Mon Sep 17 00:00:00 2001 From: Ohad Shai Date: Tue, 24 Dec 2024 08:05:26 +0200 Subject: [PATCH 5/8] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8f644ac3..0eee53ab 100644 --- a/README.md +++ b/README.md @@ -39,14 +39,14 @@ For docs and info see the [wiki](https://github.com/jasync-sql/jasync-sql/wiki). com.github.jasync-sql jasync-mysql - 2.2.0 + 2.2.4 com.github.jasync-sql jasync-postgresql - 2.2.0 + 2.2.4 ``` @@ -56,9 +56,9 @@ For docs and info see the [wiki](https://github.com/jasync-sql/jasync-sql/wiki). ```gradle dependencies { // mysql - compile 'com.github.jasync-sql:jasync-mysql:2.2.0' + compile 'com.github.jasync-sql:jasync-mysql:2.2.4' // postgresql - compile 'com.github.jasync-sql:jasync-postgresql:2.2.0' + compile 'com.github.jasync-sql:jasync-postgresql:2.2.4' } ``` From 600b782aade95bcc3c0ab4338d01cd71a0094cfa Mon Sep 17 00:00:00 2001 From: Ganzidaeyong Date: Sat, 8 Feb 2025 16:27:19 +0900 Subject: [PATCH 6/8] update spring version to 3 --- samples/spring-kotlin/README.md | 2 +- samples/spring-kotlin/build.gradle.kts | 22 +++++++++++-------- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../src/main/resources/application.properties | 2 +- .../src/main/resources/schema.sql | 8 +++++++ 5 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 samples/spring-kotlin/src/main/resources/schema.sql diff --git a/samples/spring-kotlin/README.md b/samples/spring-kotlin/README.md index d3339887..a599471a 100644 --- a/samples/spring-kotlin/README.md +++ b/samples/spring-kotlin/README.md @@ -1,2 +1,2 @@ # spring-kotlin-jasync-sql -reactive applcation base on Spring + Kotlin + [Jasync-sql](https://github.com/jasync-sql/jasync-sql) +reactive application base on Spring + Kotlin + [Jasync-sql](https://github.com/jasync-sql/jasync-sql) diff --git a/samples/spring-kotlin/build.gradle.kts b/samples/spring-kotlin/build.gradle.kts index 365ca879..852c3b94 100644 --- a/samples/spring-kotlin/build.gradle.kts +++ b/samples/spring-kotlin/build.gradle.kts @@ -5,25 +5,30 @@ version = "1.0-SNAPSHOT" plugins { application - kotlin("jvm") version "1.6.10" - kotlin("plugin.spring") version "1.6.10" - id("org.springframework.boot") version "2.6.3" + kotlin("jvm") version "1.9.25" + kotlin("plugin.spring") version "1.9.25" + id("org.springframework.boot") version "3.3.4" + id("io.spring.dependency-management") version "1.1.6" } -apply(plugin = "io.spring.dependency-management") +java { + sourceCompatibility = JavaVersion.VERSION_17 + + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } +} repositories { mavenCentral() } dependencies { - implementation(kotlin("stdlib-jdk8")) - implementation(kotlin("reflect")) implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.springframework.boot:spring-boot-starter-data-r2dbc") implementation("org.springframework.boot:spring-boot-starter-webflux") testImplementation("org.springframework.boot:spring-boot-starter-test") - runtimeOnly("com.github.jasync-sql:jasync-r2dbc-mysql:2.0.6") + runtimeOnly("com.github.jasync-sql:jasync-r2dbc-mysql:2.2.4") } tasks.test { @@ -32,7 +37,6 @@ tasks.test { tasks.withType { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" } } - diff --git a/samples/spring-kotlin/gradle/wrapper/gradle-wrapper.properties b/samples/spring-kotlin/gradle/wrapper/gradle-wrapper.properties index cc321e65..d26953ab 100644 --- a/samples/spring-kotlin/gradle/wrapper/gradle-wrapper.properties +++ b/samples/spring-kotlin/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/samples/spring-kotlin/src/main/resources/application.properties b/samples/spring-kotlin/src/main/resources/application.properties index ce1d9c32..83f4337d 100644 --- a/samples/spring-kotlin/src/main/resources/application.properties +++ b/samples/spring-kotlin/src/main/resources/application.properties @@ -1,4 +1,4 @@ server.port=8282 spring.r2dbc.url=r2dbc:mysql://localhost:3306/test spring.r2dbc.username=root -spring.r2dbc.password=123456 +spring.r2dbc.password= diff --git a/samples/spring-kotlin/src/main/resources/schema.sql b/samples/spring-kotlin/src/main/resources/schema.sql new file mode 100644 index 00000000..c829a9b7 --- /dev/null +++ b/samples/spring-kotlin/src/main/resources/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `user` ( + `username` VARCHAR(20) NOT NULL, + `password` varchar(100) NULL, + PRIMARY KEY (`username`) +); + +INSERT INTO `user` (username, password) VALUES ('Bob', 'password1'); +INSERT INTO `user` (username, password) VALUES ('Alice', 'password2'); From d72b3b4cf7bf735116b4d3f98c123333515dbb2f Mon Sep 17 00:00:00 2001 From: Ganzidaeyong Date: Sat, 8 Feb 2025 19:05:05 +0900 Subject: [PATCH 7/8] put password again, fix style in sql --- samples/spring-kotlin/src/main/resources/application.properties | 2 +- samples/spring-kotlin/src/main/resources/schema.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/spring-kotlin/src/main/resources/application.properties b/samples/spring-kotlin/src/main/resources/application.properties index 83f4337d..ce1d9c32 100644 --- a/samples/spring-kotlin/src/main/resources/application.properties +++ b/samples/spring-kotlin/src/main/resources/application.properties @@ -1,4 +1,4 @@ server.port=8282 spring.r2dbc.url=r2dbc:mysql://localhost:3306/test spring.r2dbc.username=root -spring.r2dbc.password= +spring.r2dbc.password=123456 diff --git a/samples/spring-kotlin/src/main/resources/schema.sql b/samples/spring-kotlin/src/main/resources/schema.sql index c829a9b7..109fd860 100644 --- a/samples/spring-kotlin/src/main/resources/schema.sql +++ b/samples/spring-kotlin/src/main/resources/schema.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS `user` ( `username` VARCHAR(20) NOT NULL, - `password` varchar(100) NULL, + `password` VARCHAR(100) NULL, PRIMARY KEY (`username`) ); From 4fe7c77d28f863ba1484f136a7ae1c91d1cfd95a Mon Sep 17 00:00:00 2001 From: Sungheon Jeong Date: Tue, 27 May 2025 15:47:32 +0900 Subject: [PATCH 8/8] Add Boolean Conversion Support to JasyncRow (#431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description This PR adds support for boolean type conversion in the JasyncRow class. Previously, the class supported conversions for various data types but did not explicitly handle boolean values. With these changes, the class can now properly convert various input data types (Numbers, Strings, Booleans) to Boolean values. This enhancement is particularly important for MySQL databases, which represent boolean values as TINYINT(1) where 0 means false and any non-zero value (typically 1) means true. Our implementation correctly handles this MySQL-specific behavior by treating any non-zero numeric value as true. Changes Made Extended the get method in JasyncRow to handle boolean conversions with the following mapping: Numbers: 0 → false, non-zero → true (aligned with MySQL's TINYINT(1) representation of booleans) Strings: Using Kotlin's built-in Boolean parsing Boolean values: Preserved as-is Added proper handling for primitive boolean type Added comprehensive test cases in JasyncRowTest to validate all conversion scenarios Testing Created a dedicated test class JasyncRowTest with a test method testBooleanConversion that verifies: Boolean to Boolean conversion Number to Boolean conversion (0 → false, non-zero → true) String to Boolean conversion ("true" → true, "false" → false) Accessing Boolean values by index Tests pass successfully, confirming the implementation works as expected Related Issue #430 Additional Notes This change enables more flexible type handling in the database access layer, making it easier to work with boolean values returned from MySQL queries. Since MySQL stores boolean values as TINYINT(1), this implementation ensures a seamless conversion between the database representation and the application-level Boolean type, improving type safety and code readability. --- r2dbc-mysql/src/main/java/JasyncRow.kt | 14 +++++ .../jasync/r2dbc/mysql/JasyncRowTest.kt | 55 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/JasyncRowTest.kt diff --git a/r2dbc-mysql/src/main/java/JasyncRow.kt b/r2dbc-mysql/src/main/java/JasyncRow.kt index d272c9c0..ba74c74a 100644 --- a/r2dbc-mysql/src/main/java/JasyncRow.kt +++ b/r2dbc-mysql/src/main/java/JasyncRow.kt @@ -30,6 +30,14 @@ class JasyncRow(private val rowData: RowData, private val metadata: JasyncMetada return when { requestedType == Object::class.java -> value requestedType == String::class.java -> value?.toString() + requestedType == java.lang.Boolean::class.java -> { + when (value) { + is Number -> value.toInt() != 0 + is String -> value.toBoolean() + is Boolean -> value + else -> throw IllegalStateException("Cannot convert ${value?.javaClass?.simpleName} to Boolean") + } + } value is Number -> { when (requestedType) { java.lang.Long::class.java -> value.toLong() @@ -54,6 +62,12 @@ class JasyncRow(private val rowData: RowData, private val metadata: JasyncMetada else -> throw IllegalStateException("unmatched requested type ${requestedType.simpleName}") } } + value is Boolean && requestedType.isPrimitive -> { + when (requestedType.name) { + "boolean" -> value + else -> throw IllegalStateException("Cannot convert Boolean to ${requestedType.name}") + } + } value is LocalDateTime -> { when (requestedType) { LocalDate::class.java -> value.toLocalDate() diff --git a/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/JasyncRowTest.kt b/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/JasyncRowTest.kt new file mode 100644 index 00000000..44ecad31 --- /dev/null +++ b/r2dbc-mysql/src/test/java/com/github/jasync/r2dbc/mysql/JasyncRowTest.kt @@ -0,0 +1,55 @@ +package com.github.jasync.r2dbc.mysql + +import com.github.jasync.sql.db.RowData +import io.mockk.every +import io.mockk.mockk +import org.junit.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * Unit tests for [JasyncRow]. + */ +internal class JasyncRowTest { + + @Test + fun testBooleanConversion() { + // Mock dependencies + val rowData = mockk() + val metadata = mockk() + + // Setup mock values for different types of data + every { rowData["boolTrue"] } returns true + every { rowData["boolFalse"] } returns false + every { rowData["numZero"] } returns 0 + every { rowData["numOne"] } returns 1 + every { rowData["stringTrue"] } returns "true" + every { rowData["stringFalse"] } returns "false" + every { rowData[0] } returns true + every { rowData[1] } returns 0 + every { rowData[2] } returns "true" + + val row = JasyncRow(rowData, metadata) + + // Test conversion from Boolean to Boolean + assertTrue(row.get("boolTrue", java.lang.Boolean::class.java) as Boolean) + assertFalse(row.get("boolFalse", java.lang.Boolean::class.java) as Boolean) + + // Test conversion from Number to Boolean + assertFalse(row.get("numZero", java.lang.Boolean::class.java) as Boolean) + assertTrue(row.get("numOne", java.lang.Boolean::class.java) as Boolean) + + // Test conversion from String to Boolean + assertTrue(row.get("stringTrue", java.lang.Boolean::class.java) as Boolean) + assertFalse(row.get("stringFalse", java.lang.Boolean::class.java) as Boolean) + + // Test conversion from various types using index + assertTrue(row.get(0, java.lang.Boolean::class.java) as Boolean) + assertFalse(row.get(1, java.lang.Boolean::class.java) as Boolean) + assertTrue(row.get(2, java.lang.Boolean::class.java) as Boolean) + + // Test conversion to primitive boolean - using Boolean class in Kotlin + assertTrue(row.get("boolTrue", java.lang.Boolean::class.java) as Boolean) + assertFalse(row.get("boolFalse", java.lang.Boolean::class.java) as Boolean) + } +}