diff --git a/README.md b/README.md
index 743dec73..f95eb0da 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.1.16
+ 2.1.25
com.github.jasync-sql
jasync-postgresql
- 2.1.16
+ 2.1.25
```
@@ -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.1.16'
+ compile 'com.github.jasync-sql:jasync-mysql:2.1.25'
// postgresql
- compile 'com.github.jasync-sql:jasync-postgresql:2.1.16'
+ compile 'com.github.jasync-sql:jasync-postgresql:2.1.25'
}
```
diff --git a/build.gradle.kts b/build.gradle.kts
index b351a901..19841109 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.1.25"
+ version = "2.1.26"
apply(plugin = "kotlin")
apply(plugin = "maven-publish")
diff --git a/r2dbc-mysql/src/main/java/JasyncStatement.kt b/r2dbc-mysql/src/main/java/JasyncStatement.kt
index 647eb5c0..fa014789 100644
--- a/r2dbc-mysql/src/main/java/JasyncStatement.kt
+++ b/r2dbc-mysql/src/main/java/JasyncStatement.kt
@@ -8,9 +8,11 @@ import com.github.jasync.sql.db.mysql.exceptions.MysqlErrors
import io.r2dbc.spi.Parameter
import io.r2dbc.spi.R2dbcBadGrammarException
import io.r2dbc.spi.R2dbcDataIntegrityViolationException
+import io.r2dbc.spi.R2dbcNonTransientResourceException
import io.r2dbc.spi.R2dbcPermissionDeniedException
import io.r2dbc.spi.R2dbcRollbackException
import io.r2dbc.spi.R2dbcTimeoutException
+import io.r2dbc.spi.R2dbcTransientResourceException
import io.r2dbc.spi.Result
import io.r2dbc.spi.Statement
import mu.KotlinLogging
@@ -137,50 +139,108 @@ internal class JasyncStatement(private val clientSupplier: Supplier throwable
is MySQLException -> {
val errorMessage = throwable.errorMessage
- when {
- errorMessage.errorCode == MysqlErrors.ER_DBACCESS_DENIED_ERROR -> R2dbcPermissionDeniedException(
+ when (errorMessage.errorCode) {
+ MysqlErrors.ER_DBACCESS_DENIED_ERROR,
+ MysqlErrors.ER_ACCESS_DENIED_ERROR,
+ MysqlErrors.ER_KILL_DENIED_ERROR,
+ MysqlErrors.ER_TABLEACCESS_DENIED_ERROR,
+ MysqlErrors.ER_COLUMNACCESS_DENIED_ERROR,
+ MysqlErrors.ER_SPECIFIC_ACCESS_DENIED_ERROR,
+ MysqlErrors.ER_PROCACCESS_DENIED_ERROR,
+ MysqlErrors.ER_ACCESS_DENIED_NO_PASSWORD_ERROR,
+ MysqlErrors.ER_ACCESS_DENIED_CHANGE_USER_ERROR -> R2dbcPermissionDeniedException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
throwable
)
-
- errorMessage.errorCode == MysqlErrors.ER_ACCESS_DENIED_ERROR -> R2dbcPermissionDeniedException(
+ MysqlErrors.ER_DUP_KEY,
+ MysqlErrors.ER_BAD_NULL_ERROR,
+ MysqlErrors.ER_DUP_ENTRY,
+ MysqlErrors.ER_DUP_UNIQUE,
+ MysqlErrors.ER_CANNOT_ADD_FOREIGN,
+ MysqlErrors.ER_NO_REFERENCED_ROW,
+ MysqlErrors.ER_ROW_IS_REFERENCED,
+ MysqlErrors.ER_NO_DEFAULT_FOR_FIELD,
+ MysqlErrors.ER_ROW_IS_REFERENCED_2,
+ MysqlErrors.ER_NO_REFERENCED_ROW_2,
+ MysqlErrors.ER_FOREIGN_DUPLICATE_KEY,
+ MysqlErrors.ER_DUP_UNKNOWN_IN_INDEX,
+ -> R2dbcDataIntegrityViolationException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
throwable
)
-
- errorMessage.errorCode == MysqlErrors.ER_DUP_ENTRY -> R2dbcDataIntegrityViolationException(
- errorMessage.errorMessage,
- errorMessage.sqlState,
- errorMessage.errorCode,
- throwable
- )
-
- errorMessage.errorCode == MysqlErrors.ER_PARSE_ERROR -> R2dbcBadGrammarException(
+ MysqlErrors.ER_TABLE_EXISTS_ERROR,
+ MysqlErrors.ER_BAD_TABLE_ERROR,
+ MysqlErrors.ER_BAD_FIELD_ERROR,
+ MysqlErrors.ER_PARSE_ERROR,
+ MysqlErrors.ER_ILLEGAL_REFERENCE,
+ MysqlErrors.ER_NO_SUCH_TABLE,
+ MysqlErrors.ER_SP_ALREADY_EXISTS,
+ MysqlErrors.ER_SP_DOES_NOT_EXIST,
+ MysqlErrors.ER_FUNC_INEXISTENT_NAME_COLLISION,
+ -> R2dbcBadGrammarException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
sql,
throwable
)
-
- errorMessage.errorCode == 3024 || errorMessage.errorCode == MysqlErrors.ER_QUERY_TIMEOUT -> R2dbcTimeoutException(
+ MysqlErrors.ER_LOCK_WAIT_TIMEOUT,
+ MysqlErrors.ER_QUERY_TIMEOUT,
+ 3024, -> R2dbcTimeoutException(
errorMessage.errorMessage, errorMessage.sqlState, errorMessage.errorCode, throwable
)
-
- errorMessage.errorCode == MysqlErrors.ER_XA_RBROLLBACK -> R2dbcRollbackException(
+ MysqlErrors.ER_XA_RBROLLBACK,
+ MysqlErrors.ER_XA_RBTIMEOUT -> R2dbcRollbackException(
errorMessage.errorMessage, errorMessage.sqlState, errorMessage.errorCode, throwable
)
-
- else -> JasyncDatabaseException(
- errorMessage.errorMessage,
- errorMessage.sqlState,
- errorMessage.errorCode,
- throwable
+ MysqlErrors.ER_NET_READ_INTERRUPTED,
+ MysqlErrors.ER_NET_WRITE_INTERRUPTED,
+ MysqlErrors.ER_LOCK_DEADLOCK,
+ MysqlErrors.ER_QUERY_INTERRUPTED, -> R2dbcTransientResourceException(
+ errorMessage.errorMessage, errorMessage.sqlState, errorMessage.errorCode, throwable
)
+ else -> when (errorMessage.sqlState.take(2)) {
+ "0A", "22", "26", "2F", "20", "42", "XA" -> R2dbcBadGrammarException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ "25", "28" -> R2dbcPermissionDeniedException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ "21", "23" -> R2dbcDataIntegrityViolationException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ "H1", "08" -> R2dbcNonTransientResourceException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ "40" -> R2dbcRollbackException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ else -> JasyncDatabaseException(
+ errorMessage.errorMessage,
+ errorMessage.sqlState,
+ errorMessage.errorCode,
+ throwable
+ )
+ }
}
}
diff --git a/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt b/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt
index 4c15da6e..b4b903cc 100644
--- a/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt
+++ b/r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt
@@ -15,6 +15,7 @@ import io.r2dbc.spi.ConnectionFactoryOptions.USER
import io.r2dbc.spi.ConnectionFactoryProvider
import io.r2dbc.spi.Option
import mu.KotlinLogging
+import java.nio.file.Paths
import java.time.Duration
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@@ -30,11 +31,19 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
@JvmField
val APPLICATION_NAME: Option = Option.valueOf("applicationName")
+ /**
+ * Server rsa public key file.
+ */
+ @JvmField
+ val SERVER_RSA_PUBLIC_KEY_FILE: Option = Option.valueOf("serverRSAPublicKeyFile")
+
/**
* Driver option value.
*/
const val MYSQL_DRIVER = "mysql"
+ const val MYSQL_DEFAULT_PORT = 3306
+
var CLIENT_FOUND_ROWS: Boolean by ClientFoundRowsDelegate()
init {
@@ -63,14 +72,15 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
override fun create(connectionFactoryOptions: ConnectionFactoryOptions): JasyncConnectionFactory {
val configuration = Configuration(
host = connectionFactoryOptions.getValue(HOST) as String? ?: throw IllegalArgumentException("HOST is missing"),
- port = connectionFactoryOptions.getValue(PORT) as Int? ?: throw IllegalArgumentException("PORT is missing"),
+ port = connectionFactoryOptions.getValue(PORT) as Int? ?: MYSQL_DEFAULT_PORT,
username = connectionFactoryOptions.getValue(USER) as String? ?: throw IllegalArgumentException("USER is missing"),
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?,
- ssl = MysqlSSLConfigurationFactory.create(connectionFactoryOptions)
+ ssl = MysqlSSLConfigurationFactory.create(connectionFactoryOptions),
+ rsaPublicKey = (connectionFactoryOptions.getValue(SERVER_RSA_PUBLIC_KEY_FILE) as String?)?.let { Paths.get(it) }
)
return JasyncConnectionFactory(MySQLConnectionFactory(configuration))
}
@@ -80,7 +90,6 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
return when {
driver == null || driver != MYSQL_DRIVER -> false
!connectionFactoryOptions.hasOption(HOST) -> false
- !connectionFactoryOptions.hasOption(PORT) -> false
!connectionFactoryOptions.hasOption(USER) -> false
else -> true
}
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 f44e3dc1..24edfcf5 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
@@ -11,9 +11,7 @@ class MysqlConnectionFactoryProviderTest {
@Test
fun shouldCreateMysqlConnectionWithMysqlSSLConfigurationFactory() {
-
- val options =
- ConnectionFactoryOptions.parse("r2dbc:mysql://user@host:443/")
+ val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host:443/")
// when
val result = provider.create(options)
@@ -21,4 +19,48 @@ class MysqlConnectionFactoryProviderTest {
// then
assertEquals(SSLConfiguration(), result.mySQLConnectionFactory.configuration.ssl)
}
+
+ @Test
+ fun shouldUseDefaultPortWhenPortIsNotSpecified() {
+ val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host/")
+
+ // when
+ val result = provider.create(options)
+
+ // then
+ assertEquals(3306, result.mySQLConnectionFactory.configuration.port)
+ }
+
+ @Test
+ fun shouldUseSpecifiedPort() {
+ val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host:3307/")
+
+ // when
+ val result = provider.create(options)
+
+ // then
+ assertEquals(3307, result.mySQLConnectionFactory.configuration.port)
+ }
+
+ @Test
+ fun shouldNotUseWhenRsaPublicKeyIsNotSpecified() {
+ val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host/")
+
+ // when
+ val result = provider.create(options)
+
+ // then
+ assertEquals(null, result.mySQLConnectionFactory.configuration.rsaPublicKey)
+ }
+
+ @Test
+ fun shouldUseSpecifiedRsaPublicKey() {
+ val options = ConnectionFactoryOptions.parse("r2dbc:mysql://user@host/db?serverRSAPublicKeyFile=rsa.pem")
+
+ // when
+ val result = provider.create(options)
+
+ // then
+ assertEquals("rsa.pem", result.mySQLConnectionFactory.configuration.rsaPublicKey.toString())
+ }
}