Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ allprojects {
mavenCentral()
jcenter()
maven {
url "https://repo.spring.io/libs-snapshot/"
url "https://repo.spring.io/milestone"
}
}
apply plugin: 'kotlin'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.github.jasync.sql.db.util

import com.github.jasync.sql.db.exceptions.CanceledChannelFutureException
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelFutureListener
import java.util.concurrent.CompletableFuture
Expand All @@ -9,12 +10,12 @@ import java.util.concurrent.Executor
fun ChannelFuture.toCompletableFuture(): CompletableFuture<ChannelFuture> {
val promise = CompletableFuture<ChannelFuture>()

installOnFuture(promise)
installOnChannelFuture(promise)

return promise
}

fun ChannelFuture.installOnFuture(promise: CompletableFuture<ChannelFuture>) {
fun ChannelFuture.installOnChannelFuture(promise: CompletableFuture<ChannelFuture>) {
val listener = ChannelFutureListener { future ->
if (future.isSuccess) {
promise.complete(future)
Expand All @@ -29,6 +30,21 @@ fun ChannelFuture.installOnFuture(promise: CompletableFuture<ChannelFuture>) {
}
this.addListener(listener)
}
fun ChannelFuture.installOnFuture(promise: CompletableFuture<Channel>) {
val listener = ChannelFutureListener { future ->
if (future.isSuccess) {
promise.complete(future.channel())
} else {
val exception = if (future.cause() == null) {
CanceledChannelFutureException(future)
} else {
future.cause()
}
promise.completeExceptionally(exception)
}
}
this.addListener(listener)
}


fun ChannelFuture.onFailure(executor: Executor, handler: (Throwable) -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import io.netty.bootstrap.Bootstrap
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelInitializer
Expand Down Expand Up @@ -81,9 +82,9 @@ class MySQLConnectionHandler(

fun connect(): CompletableFuture<MySQLConnectionHandler> {
this.bootstrap.channel(NettyUtils.getSocketChannelClass(this.group))
this.bootstrap.handler(object : ChannelInitializer<io.netty.channel.Channel>() {
this.bootstrap.handler(object : ChannelInitializer<Channel>() {

override fun initChannel(channel: io.netty.channel.Channel) {
override fun initChannel(channel: Channel) {
channel.pipeline().addLast(
decoder,
encoder,
Expand Down Expand Up @@ -283,11 +284,16 @@ class MySQLConnectionHandler(

fun write(message: AuthenticationSwitchResponse): ChannelFuture = writeAndHandleError(message)

fun sendQuitMessage(): CompletableFuture<ChannelFuture> {
val future = CompletableFuture<ChannelFuture>()
this.currentContext!!.channel().eventLoop().execute {
fun sendQuitMessage(): CompletableFuture<Channel> {
val future = CompletableFuture<Channel>()
val channel = this.currentContext!!.channel()
channel.eventLoop().execute {
this.clearQueryState()
writeAndHandleError(QuitMessage.Instance).installOnFuture(future)
if (channel.isActive) {
writeAndHandleError(QuitMessage.Instance).installOnFuture(future)
} else {
future.complete(channel)
}
}
return future
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,21 @@ class QuerySpec : ConnectionHelper() {
executeQuery(connection, "this is not SQL")
}
assertThat((e as MySQLException).errorMessage.sqlState).isEqualTo("#42000")
assertThat(e.errorMessage.errorCode).isEqualTo(1064)
}
}

@Test
fun `"connection" should "raise an exception upon incorrect user" `() {
val e = verifyException(ExecutionException::class.java, MySQLException::class.java) {
withConfigurableConnection(ContainerHelper.defaultConfiguration.copy(username = "not exists")) { connection ->
executeQuery(connection, "select 1")
}
}
assertThat((e as MySQLException).errorMessage.sqlState).isEqualTo("#28000")
assertThat(e.errorMessage.errorCode).isEqualTo(1045)
}


@Test
fun `"connection" should "be able to select from a table" `() {
Expand Down Expand Up @@ -322,7 +334,14 @@ class QuerySpec : ConnectionHelper() {
val interceptor = ForTestingQueryInterceptor()
MDC.put("a", "b")
val mdcInterceptor = MdcQueryInterceptorSupplier()
withConfigurablePool(ContainerHelper.defaultConfiguration.copy(interceptors = listOf(Supplier<QueryInterceptor> { interceptor }, mdcInterceptor)))
withConfigurablePool(
ContainerHelper.defaultConfiguration.copy(
interceptors = listOf(
Supplier<QueryInterceptor> { interceptor },
mdcInterceptor
)
)
)
{ connection ->
assertThat(executeQuery(connection, this.createTable).rowsAffected).isEqualTo(0)
assertThat(executeQuery(connection, this.insert).rowsAffected).isEqualTo(1)
Expand Down
2 changes: 1 addition & 1 deletion r2dbc-mysql/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
dependencies {
compile project(':mysql-async')
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
compile "io.r2dbc:r2dbc-spi:1.0.0.M7"
compile "io.r2dbc:r2dbc-spi:0.8.0.M8"
implementation "io.projectreactor:reactor-core:3.2.6.RELEASE"
compile "org.slf4j:slf4j-api:$sl4j_version"
compile "joda-time:joda-time:$joda_version"
Expand Down
8 changes: 8 additions & 0 deletions r2dbc-mysql/src/main/java/JasyncDatabaseException.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.github.jasync.r2dbc.mysql

import io.r2dbc.spi.R2dbcException

class JasyncDatabaseException(reason: String,
sqlState: String,
errorCode: Int,
cause: Throwable): R2dbcException(reason, sqlState, errorCode, cause)
4 changes: 3 additions & 1 deletion r2dbc-mysql/src/main/java/JasyncMetadata.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ class JasyncMetadata(rows: ResultSet) : RowMetadata {
return name
}
}
}

override fun getColumnNames(): Collection<String> = columnNames
}
53 changes: 52 additions & 1 deletion r2dbc-mysql/src/main/java/JasyncStatement.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package com.github.jasync.r2dbc.mysql

import com.github.jasync.sql.db.QueryResult
import com.github.jasync.sql.db.exceptions.ConnectionTimeoutedException
import com.github.jasync.sql.db.exceptions.InsufficientParametersException
import com.github.jasync.sql.db.mysql.exceptions.MySQLException
import io.r2dbc.spi.R2dbcBadGrammarException
import io.r2dbc.spi.R2dbcDataIntegrityViolationException
import io.r2dbc.spi.R2dbcPermissionDeniedException
import io.r2dbc.spi.R2dbcTimeoutException
import io.r2dbc.spi.Result
import io.r2dbc.spi.Statement
import org.reactivestreams.Publisher
import reactor.core.publisher.Mono
import reactor.core.publisher.onErrorMap
import reactor.core.publisher.toFlux
import reactor.core.publisher.toMono
import java.io.IOException
import java.util.function.Supplier
import com.github.jasync.sql.db.Connection as JasyncConnection

Expand Down Expand Up @@ -89,7 +98,49 @@ internal class JasyncStatement(private val clientSupplier: Supplier<JasyncConnec
} else {
extraGeneratedQuery(connection, connection.sendQuery(sql).toMono())
}
}.map { JasyncResult(it.rows, it.rowsAffected) }
}
.map { JasyncResult(it.rows, it.rowsAffected) }
.onErrorMap(Throwable::class) { throwable ->
when (throwable) {
is ConnectionTimeoutedException -> R2dbcTimeoutException(throwable)
is IllegalArgumentException -> throwable
is IllegalStateException -> throwable
is UnsupportedOperationException -> throwable
is IOException -> throwable
is MySQLException -> {
val errorMessage = throwable.errorMessage
when {
errorMessage.errorCode == 1044 -> R2dbcPermissionDeniedException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
throwable
)
errorMessage.errorCode == 1045 -> R2dbcPermissionDeniedException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
throwable
)
errorMessage.errorCode == 1064 -> R2dbcBadGrammarException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
sql,
throwable
)
else -> JasyncDatabaseException(
errorMessage.errorMessage,
errorMessage.sqlState,
errorMessage.errorCode,
throwable
)
}
}
is InsufficientParametersException -> R2dbcDataIntegrityViolationException(throwable.message, throwable)
else -> R2dbcTimeoutException(throwable)
}
}
}

private fun extraGeneratedQuery(connection: JasyncConnection, result: Mono<QueryResult>): Mono<QueryResult> {
Expand Down
2 changes: 2 additions & 0 deletions r2dbc-mysql/src/main/java/MysqlConnectionFactoryProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ class MysqlConnectionFactoryProvider : ConnectionFactoryProvider {
else -> true
}
}

override fun getDriver(): String = MYSQL_DRIVER
}