diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt index 8dddea0..acf1e90 100644 --- a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt @@ -13,7 +13,6 @@ import io.vertx.core.buffer.Buffer import io.vertx.kotlin.coroutines.coAwait import io.vertx.kotlin.sqlclient.poolOptionsOf import io.vertx.pgclient.PgConnectOptions -import io.vertx.pgclient.PgConnection import io.vertx.pgclient.PgPool import io.vertx.sqlclient.* import kotlinx.coroutines.coroutineScope @@ -387,20 +386,20 @@ fun Int.singleOrNoUpdate() = * When using this function, it's recommended to name the lambda parameter the same as the outer receiver so that the outer [DatabaseClient] is shadowed, * and so that you don't call the outer [DatabaseClient] without a transaction by accident. */ -suspend fun DatabaseClient.withTransaction(function: suspend (DatabaseClient) -> T): T = +suspend fun DatabaseClient.withTransaction(function: suspend (DatabaseClient) -> T): T = coroutineScope { vertxSqlClient.withTransaction { coroutineToFuture { function(DatabaseClient(it, exposedDatabase)) } }.coAwait() } -suspend fun DatabaseClient.withPgTransaction(function: suspend (DatabaseClient) -> T): T = +suspend fun DatabaseClient.withTypedTransaction(function: suspend (DatabaseClient) -> T): T = withTransaction { @Suppress("UNCHECKED_CAST") - function(it as DatabaseClient) + function(it as DatabaseClient) } -suspend fun DatabaseClient.withTransactionCommitOrRollback(function: suspend (DatabaseClient) -> Option): Option { +suspend fun DatabaseClient.withTransactionCommitOrRollback(function: suspend (DatabaseClient) -> Option): Option { val transaction = vertxSqlClient.begin().coAwait() return try { val result = function(this) @@ -417,21 +416,21 @@ suspend fun DatabaseClient.withTransactionCommitOrRollback(fu val savepointNameRegex = Regex("\\w+") -private suspend fun DatabaseClient.savepoint(savepointName: String) = +private suspend fun DatabaseClient.savepoint(savepointName: String) = executePlainSqlUpdate("SAVEPOINT \"$savepointName\"").also { dbAssert(it == 0) } -private suspend fun DatabaseClient.rollbackToSavepoint(savepointName: String) = +private suspend fun DatabaseClient.rollbackToSavepoint(savepointName: String) = executePlainSqlUpdate("ROLLBACK TO SAVEPOINT \"$savepointName\"").also { dbAssert(it == 0) } -private suspend fun DatabaseClient.releaseSavepoint(savepointName: String) = +private suspend fun DatabaseClient.releaseSavepoint(savepointName: String) = executePlainSqlUpdate("RELEASE SAVEPOINT \"$savepointName\"").also { dbAssert(it == 0) } /** - * Currently only available for PostgreSQL. + * Not tested yet on DBs other than PostgreSQL. * A savepoint destroys one with the same name so be careful. */ -suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrLeft( - savepointName: String, function: suspend (DatabaseClient) -> Either +suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrLeft( + savepointName: String, function: suspend (DatabaseClient) -> Either ): Either { // Prepared query seems not to work here. @@ -451,18 +450,18 @@ suspend fun DatabaseClient.withSavepointAndR } } -suspend fun DatabaseClient.withSavepointAndRollbackIfThrows( - savepointName: String, function: suspend (DatabaseClient) -> T +suspend fun DatabaseClient.withSavepointAndRollbackIfThrows( + savepointName: String, function: suspend (DatabaseClient) -> T ): T = withSavepointAndRollbackIfThrowsOrLeft(savepointName) { function(it).right() }.getOrElse { throw AssertionError() } -suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrNone( - savepointName: String, function: suspend (DatabaseClient) -> Option +suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrNone( + savepointName: String, function: suspend (DatabaseClient) -> Option ): Option = withSavepointAndRollbackIfThrowsOrLeft(savepointName) { function(it).toEither { } }.getOrNone() -suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrFalse( - savepointName: String, function: suspend (DatabaseClient) -> Boolean +suspend fun DatabaseClient.withSavepointAndRollbackIfThrowsOrFalse( + savepointName: String, function: suspend (DatabaseClient) -> Boolean ): Boolean = withSavepointAndRollbackIfThrowsOrLeft(savepointName) { if (function(it)) Unit.right() else Unit.left() }.isRight() diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClient.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClient.kt new file mode 100644 index 0000000..54ea5d2 --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClient.kt @@ -0,0 +1,9 @@ +package com.huanshankeji.exposedvertxsqlclient.postgresql + +import com.huanshankeji.exposedvertxsqlclient.DatabaseClient +import com.huanshankeji.exposedvertxsqlclient.withTypedTransaction +import io.vertx.pgclient.PgConnection +import io.vertx.sqlclient.Pool + +suspend fun DatabaseClient.withPgTransaction(function: suspend (DatabaseClient) -> T): T = + withTypedTransaction(function)