diff --git a/README.md b/README.md index 5322a8f..9b12cf6 100644 --- a/README.md +++ b/README.md @@ -8,25 +8,89 @@ Only PostgreSQL with [Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/) is currently supported. -## Maven coordinate +## Experimental + +This library is experimental now. The APIs are subject to change (especially those marked with `@ExperimentalEvscApi`), the tests are incomplete, and please expect bugs and report them. + +## Add to your dependencies + +### The Maven coordinates ```kotlin -"com.huanshankeji:exposed-vertx-sql-client-postgresql:$version" +"com.huanshankeji:exposed-vertx-sql-client-$module:$libraryVersion" ``` +### **Important note** + +As Exposed is a library that has not reached stability yet and often has incompatible changes, you are recommended to stick to the same version of Exposed used by this library. The current version is v0.56.0. + +## API documentation + +See the [hosted API documentation](https://huanshankeji.github.io/exposed-vertx-sql-client/) for the APIs. + ## Basic usage guide -Here is a basic usage guide. This project currently serves our own use, therefore, there are temporarily no detailed docs, APIs are experimental, tests are incomplete, and please expect bugs. To learn more in addition to the guide below, see the [hosted API documentation](https://huanshankeji.github.io/exposed-vertx-sql-client/), and see [DatabaseClient.kt](lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt) and [DatabaseClientSql.kt](lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt) for the major APIs. +Here is a basic usage guide. + +### Before v0.5.0 + +Add the PostgreSQL module, which was the only module, to your dependencies with the Gradle build script: + +```kotlin +implementation("com.huanshankeji:exposed-vertx-sql-client-postgresql:$libraryVersion") +``` + +### Since v0.5.0 + +Add the core module to your dependencies with the Gradle build script: + +```kotlin +implementation("com.huanshankeji:exposed-vertx-sql-client-core:$libraryVersion") +``` + +And add an RDBMS module, for example, the PostgreSQL module: + +```kotlin +implementation("com.huanshankeji:exposed-vertx-sql-client-postgresql:$libraryVersion") +``` ### Create a `DatabaseClient` +Create an `EvscConfig` as the single source of truth: + +```kotlin +val evscConfig = ConnectionConfig.Socket("localhost", user = "user", password = "password", database = "database") + .toUniversalEvscConfig() +``` + +Local alternative with Unix domain socket: + +```kotlin +val evscConfig = defaultPostgresqlLocalConnectionConfig( + user = "user", + socketConnectionPassword = "password", + database = "database" +).toPerformantUnixEvscConfig() +``` + +Create an Exposed `Database` with the `ConnectionConfig.Socket`, which can be shared and reused in multiple `Verticle`s: + +```kotlin +val exposedDatabase = evscConfig.exposedConnectionConfig.exposedDatabaseConnectPostgresql() +``` + +Create a Vert.x `SqlClient` with the `ConnectionConfig`, preferably in a `Verticle`: + +```kotlin +val sqlClient = createPgClient(vertx, evscConfig.vertxSqlClientConnectionConfig) +val pool = createPgPool(vertx, evscConfig.vertxSqlClientConnectionConfig) +val sqlConnection = createPgClient(vertx, evscConfig.vertxSqlClientConnectionConfig) +``` + +Create a `Database` with the provided Vert.x `SqlClient` and Exposed `Database`, preferably in a `Verticle`: + ```kotlin -val socketConnectionConfig = - ConnectionConfig.Socket("localhost", user = "user", password = "password", database = "database") -val exposedDatabase = exposedDatabaseConnectPostgreSql(socketConnectionConfig) -val databaseClient = createPgPoolDatabaseClient( - vertx, socketConnectionConfig, exposedDatabase = exposedDatabase -) +val databaseClient = DatabaseClient(vertxSqlClient, exposedDatabase) ``` ### Example table definitions @@ -44,18 +108,19 @@ val tables = arrayOf(Examples) For example, to create tables: ```kotlin -withContext(Dispatchers.IO) { - databaseClient.exposedTransaction { - SchemaUtils.create(*tables) - } +databaseClient.exposedTransaction { + SchemaUtils.create(*tables) } ``` +If you execute blocking Exposed statements inside `Verticle`s or event loop threads that you shouldn't block, you should use Vert.x `Vertx.executeBlocking` or Coroutines `Dispatchers.IO`. + ### CRUD (DML and DQL) operations with `DatabaseClient` #### Core APIs -With these core APIs, you create and execute Exposed `Statement`s. You don't need to learn many new APIs, and the `Statement`s are more composable and easily editable. +With these core APIs, you create and execute Exposed `Statement`s. You don't need to learn many new APIs, and the +`Statement`s are more composable and easily editable. For example, you can move a query into an adapted subquery. ```kotlin // The Exposed `Table` extension functions `insert`, `update`, and `delete` execute eagerly so `insertStatement`, `updateStatement`, `deleteStatement` have to be used. @@ -82,7 +147,15 @@ databaseClient.executeSingleUpdate(Examples.deleteIgnoreWhereStatement { id eq 2 #### Extension SQL DSL APIs -With these extension APIs, your code becomes more concise, but it might be more difficult when you need to compose statements or edit the code: +With the extension SQL DSL APIs, your code becomes more concise, but it might be more difficult when you need to compose statements or edit the code. + +Gradle dependency configuration (only needed since v0.5.0): + +```kotlin +implementation("com.huanshankeji:exposed-vertx-sql-client-sql-dsl:$libraryVersion") +``` + +Example code: ```kotlin databaseClient.insert(Examples) { it[name] = "A" } @@ -94,7 +167,9 @@ val exampleName1 = databaseClient.select(Examples) { select(Examples.name).where(Examples.id eq 1) }.single()[Examples.name] // This function still depends on the old SELECT DSL and will be updated. val exampleName2 = - databaseClient.selectSingleColumn(Examples, Examples.name) { selectAll().where(Examples.id eq 2) }.single() + databaseClient.selectSingleColumn(Examples, Examples.name) { where(Examples.id eq 2) }.single() + +val examplesExist = databaseClient.selectExpression(exists(Examples.selectAll())) val deleteRowCount1 = databaseClient.deleteWhere(Examples) { id eq 1 } assert(deleteRowCount1 == 1) @@ -102,26 +177,34 @@ val deleteRowCount2 = databaseClient.deleteIgnoreWhere(Examples) { id eq 2 } assert(deleteRowCount2 == 1) ``` -#### APIs using [Exposed GADT mapping](https://github.com/huanshankeji/exposed-adt-mapping) +#### Extension SQL DSL APIs with [Exposed GADT mapping](https://github.com/huanshankeji/exposed-adt-mapping) Please read [that library's basic usage guide](https://github.com/huanshankeji/exposed-adt-mapping?tab=readme-ov-file#basic-usage-guide) first. Here are examples of this library that correspond to [that library's CRUD operations](https://github.com/huanshankeji/exposed-adt-mapping?tab=readme-ov-file#crud-operations). +Gradle dependency configuration (only needed since v0.5.0): + +```kotlin +implementation("com.huanshankeji:exposed-vertx-sql-client-sql-dsl-with-mapper:$libraryVersion") +``` + +Example code: + ```kotlin val directorId = 1 val director = Director(directorId, "George Lucas") -databaseClient.insert(Directors, director, Mappers.director) +databaseClient.insertWithMapper(Directors, director, Mappers.director) val episodeIFilmDetails = FilmDetails(1, "Star Wars: Episode I – The Phantom Menace", directorId) // insert without the ID since it's `AUTO_INCREMENT` -databaseClient.insert(Films, episodeIFilmDetails, Mappers.filmDetailsWithDirectorId) +databaseClient.insertWithMapper(Films, episodeIFilmDetails, Mappers.filmDetailsWithDirectorId) val filmId = 2 val episodeIIFilmDetails = FilmDetails(2, "Star Wars: Episode II – Attack of the Clones", directorId) val filmWithDirectorId = FilmWithDirectorId(filmId, episodeIIFilmDetails) -databaseClient.insert(Films, filmWithDirectorId, Mappers.filmWithDirectorId) // insert with the ID +databaseClient.insertWithMapper(Films, filmWithDirectorId, Mappers.filmWithDirectorId) // insert with the ID -val fullFilms = databaseClient.select(filmsLeftJoinDirectors, Mappers.fullFilm) { - select(Films.filmId inList listOf(1, 2)) // This API still depends on the old SELECT DSL and will be refactored. +val fullFilms = databaseClient.selectWithMapper(filmsLeftJoinDirectors, Mappers.fullFilm) { + where(Films.filmId inList listOf(1, 2)) // This API still depends on the old SELECT DSL and will be refactored. } ``` diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 6a6f9e2..cab0d18 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,6 +18,6 @@ dependencies { // With Kotlin 2.0.20, a "Could not parse POM" build error occurs in the JVM projects of some dependent projects. implementation(kotlin("gradle-plugin", "2.0.10")) implementation("com.huanshankeji:common-gradle-dependencies:0.8.0-20241016") // don't use a snapshot version in a main branch - implementation("com.huanshankeji.team:gradle-plugins:0.6.0") // don't use a snapshot version in a main branch + implementation("com.huanshankeji.team:gradle-plugins:0.7.0") // don't use a snapshot version in a main branch implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.0.0-Beta") } diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index bbeefd8..f784f2d 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -2,13 +2,13 @@ import com.huanshankeji.CommonDependencies import com.huanshankeji.CommonGradleClasspathDependencies import com.huanshankeji.CommonVersions -val projectVersion = "0.4.0-SNAPSHOT" +val projectVersion = "0.5.0-SNAPSHOT" // don't use a snapshot version in a main branch -val commonVersions = CommonVersions(kotlinCommon = "0.5.1") +val commonVersions = CommonVersions(kotlinCommon = "0.6.0", exposed = "0.56.0") val commonDependencies = CommonDependencies(commonVersions) val commonGradleClasspathDependencies = CommonGradleClasspathDependencies(commonVersions) object DependencyVersions { - val exposedAdtMapping = "0.2.0" + val exposedAdtMapping = "0.3.0" // don't use a snapshot version in a main branch } diff --git a/buildSrc/src/main/kotlin/conventions.gradle.kts b/buildSrc/src/main/kotlin/conventions.gradle.kts index adb9b61..922292b 100644 --- a/buildSrc/src/main/kotlin/conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/conventions.gradle.kts @@ -1,12 +1,9 @@ -import com.huanshankeji.team.`Shreck Ye` -import com.huanshankeji.team.pomForTeamDefaultOpenSource import com.huanshankeji.team.repositoriesAddTeamGithubPackagesMavenRegistry -import org.gradle.kotlin.dsl.repositories +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask plugins { id("com.huanshankeji.team.with-group") - id("com.huanshankeji.kotlin-jvm-library-sonatype-ossrh-publish-conventions") - id("com.huanshankeji.team.default-github-packages-maven-publish") + kotlin("jvm") } repositories { @@ -19,8 +16,6 @@ kotlin.jvmToolchain(8) version = projectVersion -publishing.publications.getByName("maven") { - pomForTeamDefaultOpenSource(project, "Exposed Vert.x SQL Client", "Exposed on top of Vert.x Reactive SQL Client") { - `Shreck Ye`() - } +tasks.named>("compileKotlin").configure { + compilerOptions.freeCompilerArgs.add("-opt-in=com.huanshankeji.exposedvertxsqlclient.InternalApi") } diff --git a/buildSrc/src/main/kotlin/lib-conventions.gradle.kts b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts new file mode 100644 index 0000000..e679e3d --- /dev/null +++ b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts @@ -0,0 +1,15 @@ +import com.huanshankeji.team.`Shreck Ye` +import com.huanshankeji.team.pomForTeamDefaultOpenSource + +plugins { + id("conventions") + id("com.huanshankeji.kotlin-jvm-library-sonatype-ossrh-publish-conventions") + id("com.huanshankeji.team.default-github-packages-maven-publish") + id("com.huanshankeji.team.dokka.github-dokka-convention") +} + +publishing.publications.getByName("maven") { + pomForTeamDefaultOpenSource(project, "Exposed Vert.x SQL Client", "Exposed on top of Vert.x Reactive SQL Client") { + `Shreck Ye`() + } +} diff --git a/core/api/exposed-vertx-sql-client-core.api b/core/api/exposed-vertx-sql-client-core.api new file mode 100644 index 0000000..fe39f10 --- /dev/null +++ b/core/api/exposed-vertx-sql-client-core.api @@ -0,0 +1,172 @@ +public abstract interface class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { + public abstract fun getDatabase ()Ljava/lang/String; + public abstract fun getUserAndRole ()Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket : com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { + public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun getDatabase ()Ljava/lang/String; + public final fun getHost ()Ljava/lang/String; + public final fun getPassword ()Ljava/lang/String; + public final fun getPort ()Ljava/lang/Integer; + public final fun getUser ()Ljava/lang/String; + public fun getUserAndRole ()Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig$UnixDomainSocketWithPeerAuthentication : com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { + public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public fun getDatabase ()Ljava/lang/String; + public final fun getPath ()Ljava/lang/String; + public final fun getRole ()Ljava/lang/String; + public fun getUserAndRole ()Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/ConnectionConfigKt { + public static final fun toUniversalEvscConfig (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;)Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; +} + +public final class com/huanshankeji/exposedvertxsqlclient/ConnectionType : java/lang/Enum { + public static final field Socket Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; + public static final field UnixDomainSocketWithPeerAuthentication Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; + public static fun getEntries ()Lkotlin/enums/EnumEntries; + public static fun valueOf (Ljava/lang/String;)Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; + public static fun values ()[Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; +} + +public final class com/huanshankeji/exposedvertxsqlclient/DatabaseClient : com/huanshankeji/kotlinx/coroutine/CoroutineAutoCloseable { + public fun (Lio/vertx/sqlclient/SqlClient;Lorg/jetbrains/exposed/sql/Database;ZZ)V + public synthetic fun (Lio/vertx/sqlclient/SqlClient;Lorg/jetbrains/exposed/sql/Database;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun createTable (Lorg/jetbrains/exposed/sql/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun doExecute (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun dropTable (Lorg/jetbrains/exposed/sql/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun execute (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeBatch (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeBatchForVertxSqlClientRowSetSequence (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeBatchQuery (Lorg/jetbrains/exposed/sql/FieldSet;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeBatchQuery (Lorg/jetbrains/exposed/sql/FieldSet;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeBatchUpdate (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeExpression (Lkotlin/reflect/KClass;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeForVertxSqlClientRowSet (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executePlainSql (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executePlainSqlUpdate (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeQuery (Lorg/jetbrains/exposed/sql/Query;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeQuery (Lorg/jetbrains/exposed/sql/Query;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeSingleOrNoUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeSingleUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun executeWithMapping (Lorg/jetbrains/exposed/sql/statements/Statement;Ljava/util/function/Function;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun exposedTransaction (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public final fun getExposedDatabase ()Lorg/jetbrains/exposed/sql/Database; + public final fun getFieldExpressionSetWithTransaction (Lorg/jetbrains/exposed/sql/FieldSet;)Ljava/util/Set; + public final fun getFieldExpressionSetWithTransaction (Lorg/jetbrains/exposed/sql/Query;)Ljava/util/Set; + public final fun getLogSql ()Z + public final fun getValidateBatch ()Z + public final fun getVertxSqlClient ()Lio/vertx/sqlclient/SqlClient; + public final fun isWorking (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun toExposedResultRowWithTransaction (Lio/vertx/sqlclient/Row;Lorg/jetbrains/exposed/sql/Query;)Lorg/jetbrains/exposed/sql/ResultRow; +} + +public final class com/huanshankeji/exposedvertxsqlclient/DatabaseClientKt { + public static final fun dbAssert (Z)V + public static final fun getFieldExpressionSet (Lorg/jetbrains/exposed/sql/FieldSet;)Ljava/util/Set; + public static final fun getFieldExpressionSet (Lorg/jetbrains/exposed/sql/Query;)Ljava/util/Set; + public static final fun getSavepointNameRegex ()Lkotlin/text/Regex; + public static final fun getVertxPgClientPreparedSql (Lorg/jetbrains/exposed/sql/statements/Statement;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; + public static final fun getVertxSqlClientArgTuple (Lorg/jetbrains/exposed/sql/statements/Statement;)Lio/vertx/sqlclient/Tuple; + public static final fun singleOrNoResult (Lio/vertx/sqlclient/RowSet;)Ljava/lang/Object; + public static final fun singleOrNoUpdate (I)Z + public static final fun singleResult (Lio/vertx/sqlclient/RowSet;)Ljava/lang/Object; + public static final fun singleStatementArguments (Lorg/jetbrains/exposed/sql/statements/Statement;)Ljava/lang/Iterable; + public static final fun toExposedResultRow (Lio/vertx/sqlclient/Row;Ljava/util/Set;)Lorg/jetbrains/exposed/sql/ResultRow; + public static final fun toExposedResultRow (Lio/vertx/sqlclient/Row;Lorg/jetbrains/exposed/sql/Query;)Lorg/jetbrains/exposed/sql/ResultRow; + public static final fun toVertxPgClientPreparedSql (Ljava/lang/String;)Ljava/lang/String; + public static final fun toVertxTuple (Ljava/lang/Iterable;)Lio/vertx/sqlclient/Tuple; + public static final fun types (Ljava/lang/Iterable;)Ljava/util/List; + public static final fun withSavepointAndRollbackIfThrows (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withSavepointAndRollbackIfThrowsOrFalse (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withSavepointAndRollbackIfThrowsOrLeft (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withSavepointAndRollbackIfThrowsOrNone (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withTransaction (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withTransactionCommitOrRollback (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun withTypedTransaction (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class com/huanshankeji/exposedvertxsqlclient/EvscConfig : com/huanshankeji/exposedvertxsqlclient/IEvscConfig { + public fun (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;)V + public fun getExposedConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; + public fun getVertxSqlClientConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig; +} + +public abstract interface annotation class com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi : java/lang/annotation/Annotation { +} + +public abstract interface class com/huanshankeji/exposedvertxsqlclient/IEvscConfig { + public abstract fun getExposedConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; + public abstract fun getVertxSqlClientConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig; +} + +public abstract interface annotation class com/huanshankeji/exposedvertxsqlclient/InternalApi : java/lang/annotation/Annotation { +} + +public final class com/huanshankeji/exposedvertxsqlclient/SingleUpdateException : java/lang/Exception { + public fun (I)V +} + +public final class com/huanshankeji/exposedvertxsqlclient/exposed/ExposedDatabasesKt { + public static final fun exposedDatabaseConnect (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Database; + public static final fun exposedDatabaseConnect (Ljava/lang/String;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Database; + public static synthetic fun exposedDatabaseConnect$default (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Database; + public static synthetic fun exposedDatabaseConnect$default (Ljava/lang/String;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Database; +} + +public final class com/huanshankeji/exposedvertxsqlclient/jdbc/JdbcUrlsKt { + public static final fun jdbcUrl (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Ljava/lang/String;)Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig { + public static final field Companion Lcom/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig$Companion; + public static final field SOCKET_HOST Ljava/lang/String; + public fun (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public synthetic fun (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getConnectionConfig (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType;)Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig; + public final fun getDatabase ()Ljava/lang/String; + public final fun getSocketConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; + public final fun getSocketConnectionPassword ()Ljava/lang/String; + public final fun getSocketConnectionPort ()Ljava/lang/Integer; + public final fun getUnixDomainSocketPath ()Ljava/lang/String; + public final fun getUnixDomainSocketWithPeerAuthenticationConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$UnixDomainSocketWithPeerAuthentication; + public final fun getUser ()Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig$Companion { +} + +public final class com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfigKt { + public static final fun toPerformantUnixEvscConfig (Lcom/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig;)Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; + public static final fun toUniversalEvscConfig (Lcom/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig;)Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; +} + +public final class com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlClientsKt { + public static final fun createGenericSqlClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lio/vertx/sqlclient/SqlConnectOptions;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;)Lio/vertx/sqlclient/SqlClient; + public static final fun createGenericSqlClientWithBuilder (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lio/vertx/sqlclient/ClientBuilder;Lio/vertx/sqlclient/SqlConnectOptions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/sqlclient/SqlClient; + public static final fun createGenericSqlConnection (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function2;Lio/vertx/sqlclient/SqlConnectOptions;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectOptionsKt { + public static final fun setFrom (Lio/vertx/sqlclient/SqlConnectOptions;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;)V + public static final fun setFrom (Lio/vertx/sqlclient/SqlConnectOptions;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$UnixDomainSocketWithPeerAuthentication;)V + public static final fun setFrom (Lio/vertx/sqlclient/SqlConnectOptions;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;)V +} + +public final class com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectionInitializationKt { + public static final fun getCoConnectHandler (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; + public static final fun initConnection (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lio/vertx/sqlclient/SqlConnection;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun toWithParameterFunction (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; +} + +public final class com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectionKt { + public static final fun setRole (Lio/vertx/sqlclient/SqlConnection;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 0000000..5b5c918 --- /dev/null +++ b/core/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + `lib-conventions` +} + +dependencies { + api(commonDependencies.exposed.core()) // TODO: use `implementation` when possible + api(commonDependencies.kotlinCommon.exposed()) + + with(commonDependencies.vertx) { + implementation(platformStackDepchain()) + api(moduleWithoutVersion("sql-client")) // TODO: use `implementation` when possible + implementation(moduleWithoutVersion("lang-kotlin")) + implementation(moduleWithoutVersion("lang-kotlin-coroutines")) + } + implementation(commonDependencies.kotlinCommon.vertx()) + + implementation(commonDependencies.kotlinCommon.core()) + implementation(commonDependencies.arrow.core()) + + implementation(commonDependencies.kotlinCommon.net()) + + api(commonDependencies.kotlinCommon.coroutines()) // Exposed the `use` function +} diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt similarity index 77% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt rename to core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt index 09c7365..cfbb80a 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionConfig.kt @@ -1,5 +1,7 @@ package com.huanshankeji.exposedvertxsqlclient +import com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient.setRole + sealed interface ConnectionConfig { val userAndRole: String val database: String @@ -14,6 +16,9 @@ sealed interface ConnectionConfig { override val userAndRole: String get() = user } + /** + * @see setRole + */ class UnixDomainSocketWithPeerAuthentication( val path: String, val role: String, @@ -21,4 +26,7 @@ sealed interface ConnectionConfig { ) : ConnectionConfig { override val userAndRole: String get() = role } -} \ No newline at end of file +} + +fun ConnectionConfig.Socket.toUniversalEvscConfig() = + EvscConfig(this, this) diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt similarity index 71% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt rename to core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt index 54d1b56..03ff607 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ConnectionType.kt @@ -1,5 +1,6 @@ package com.huanshankeji.exposedvertxsqlclient +//@Deprecated("This class seems no longer used.") enum class ConnectionType { Socket, UnixDomainSocketWithPeerAuthentication } \ No newline at end of file diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt similarity index 73% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt rename to core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt index b82985e..ba3b423 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/DatabaseClient.kt @@ -1,26 +1,18 @@ package com.huanshankeji.exposedvertxsqlclient import arrow.core.* +import com.huanshankeji.ExperimentalApi import com.huanshankeji.collections.singleOrNullIfEmpty -import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig.Socket -import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig.UnixDomainSocketWithPeerAuthentication -import com.huanshankeji.exposedvertxsqlclient.sql.selectExpression -import com.huanshankeji.os.isCurrentOsLinux +import com.huanshankeji.kotlinx.coroutine.CoroutineAutoCloseable import com.huanshankeji.vertx.kotlin.coroutines.coroutineToFuture import com.huanshankeji.vertx.kotlin.sqlclient.executeBatchAwaitForSqlResultSequence -import io.vertx.core.Vertx 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 import org.jetbrains.exposed.dao.id.EntityID import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.Query -import org.jetbrains.exposed.sql.Transaction import org.jetbrains.exposed.sql.statements.InsertStatement import org.jetbrains.exposed.sql.statements.Statement import org.jetbrains.exposed.sql.statements.UpdateStatement @@ -73,8 +65,8 @@ fun String.toVertxPgClientPreparedSql(): String { fun Statement<*>.getVertxPgClientPreparedSql(transaction: ExposedTransaction) = prepareSQL(transaction).toVertxPgClientPreparedSql() - -internal fun dbAssert(b: Boolean) { +@InternalApi +fun dbAssert(b: Boolean) { if (!b) throw AssertionError() } @@ -85,30 +77,33 @@ internal val logger = LoggerFactory.getLogger(DatabaseClient::class.java) /** * A wrapper client around Vert.x [SqlClient] for queries and an Exposed [Database] to generate SQLs working around the limitations of Exposed. * - * @param validateBatch whether to validate whether the batch statements have the same generated prepared SQL. + * @param validateBatch whether to validate whether the batch statements have the same generated prepared SQL. It's recommended to keep this enabled for tests but disabled for production. */ -@OptIn(ExperimentalEvscApi::class) -class DatabaseClient( - val vertxSqlClient: VertxSqlClient, +@OptIn(ExperimentalApi::class) +class DatabaseClient( + val vertxSqlClient: VertxSqlClientT, val exposedDatabase: Database, + // TODO consider adding a `isProduction` parameter whose default depends on the runtime val validateBatch: Boolean = true, val logSql: Boolean = false -) { - suspend fun close() { +) : CoroutineAutoCloseable { + override suspend fun close() { vertxSqlClient.close().coAwait() // How to close The Exposed `Database`? } + // TODO consider splitting into 2, one with `readOnly` set to true and isolation level `NONE` / READ UNCOMMITED for SQL generation, and a normal one for Exposed execution + // TODO also consider adding the 2 parameters `transactionIsolation` and `readOnly` with default arguments fun exposedTransaction(statement: ExposedTransaction.() -> T) = transaction(exposedDatabase, statement) - private fun Statement<*>.prepareSqlAndLogIfNeeded(transaction: Transaction) = + private fun Statement<*>.prepareSqlAndLogIfNeeded(transaction: ExposedTransaction) = prepareSQL(transaction).also { if (logSql) logger.info("Prepared SQL: $it.") } suspend fun executePlainSql(sql: String): RowSet = - /** Use [SqlClient.preparedQuery] here because of [PgConnectOptions.setCachePreparedStatements]. */ + /** Use [SqlClient.preparedQuery] here because of [SqlConnectOptions.setCachePreparedStatements]. */ vertxSqlClient.preparedQuery(sql).execute().coAwait() suspend fun executePlainSqlUpdate(sql: String): Int = @@ -123,7 +118,12 @@ class DatabaseClient( */ @Deprecated( "This function does not support analyzing dependencies among tables. Since this action is not frequently needed we can adopt the blocking approach. Use Exposed `SchemaUtils` and create multiple tables in batch instead, temporarily.", - ReplaceWith("exposedTransaction { SchemaUtils.create(table) }", "org.jetbrains.exposed.sql.SchemaUtils") + ReplaceWith( + "withContext(Dispatchers.IO) { exposedTransaction { SchemaUtils.create(table) } }", + "kotlinx.coroutines.withContext", + "kotlinx.coroutines.Dispatchers", + "org.jetbrains.exposed.sql.SchemaUtils" + ) ) suspend fun createTable(table: Table) = executePlainSqlUpdate(exposedTransaction { @@ -133,7 +133,13 @@ class DatabaseClient( @Deprecated( "This function does not support analyzing dependencies among tables. Since this action is not frequently needed we can adopt the blocking approach. Use Exposed `SchemaUtils` and drop multiple tables in batch instead, temporarily.", - ReplaceWith("exposedTransaction { SchemaUtils.drop(table) }", "org.jetbrains.exposed.sql.SchemaUtils") + // TODO `Dispatchers.IO` + ReplaceWith( + "withContext(Dispatchers.IO) { exposedTransaction { SchemaUtils.drop(table) } }", + "kotlinx.coroutines.withContext", + "kotlinx.coroutines.Dispatchers", + "org.jetbrains.exposed.sql.SchemaUtils" + ) ) suspend fun dropTable(table: Table) = executePlainSqlUpdate(exposedTransaction { @@ -205,20 +211,20 @@ class DatabaseClient( @Deprecated( - "Use `selectExpression` instead`", + "Use `selectExpression` in the \"sql-dsl\" module instead.", ReplaceWith( "selectExpression(clazz, expression)", "com.huanshankeji.exposedvertxsqlclient.sql.selectExpression" ) ) suspend fun executeExpression(clazz: KClass, expression: Expression): T? = - selectExpression(clazz, expression) + throw NotImplementedError() @Deprecated( - "Use `selectExpression` instead`", + "Use `selectExpression` in the \"sql-dsl\" module instead.", ReplaceWith("selectExpression(expression)", "com.huanshankeji.exposedvertxsqlclient.sql.selectExpression") ) suspend inline fun executeExpression(expression: Expression): T = - selectExpression(expression) + throw NotImplementedError() suspend fun isWorking(): Boolean = try { @@ -290,6 +296,9 @@ class DatabaseClient( suspend fun executeBatchForVertxSqlClientRowSetSequence(statements: Iterable>): Sequence> = executeBatch(statements) { this } + /** + * @see executeBatch + */ @ExperimentalEvscApi suspend inline fun executeBatchQuery( fieldSet: FieldSet, queries: Iterable, crossinline resultRowMapper: ResultRow.() -> Data @@ -310,7 +319,7 @@ class DatabaseClient( */ /** * Executes a batch of update statements, including [InsertStatement] and [UpdateStatement]. - * @see org.jetbrains.exposed.sql.batchInsert + * @see executeBatch * @return a sequence of the update counts of the update statements in the batch. */ suspend fun executeBatchUpdate( @@ -384,20 +393,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) @@ -414,21 +423,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. @@ -448,89 +457,17 @@ 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() - -// TODO: use `ConnectionConfig` as the argument directly - -// can be used for a shared Exposed `Database` among `DatabaseClient`s -fun createPgPoolDatabaseClient( - vertx: Vertx?, - vertxSqlClientConnectionConfig: ConnectionConfig, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf(), - exposedDatabase: Database -): DatabaseClient = - DatabaseClient( - with(vertxSqlClientConnectionConfig) { - when (this) { - is Socket -> - createSocketPgPool(vertx, host, port, database, user, password, extraPgConnectOptions, poolOptions) - - is UnixDomainSocketWithPeerAuthentication -> - createPeerAuthenticationUnixDomainSocketPgPoolAndSetRole( - vertx, path, database, role, extraPgConnectOptions, poolOptions - ) - } - }, - exposedDatabase - ) - -fun createPgPoolDatabaseClient( - vertx: Vertx?, - vertxSqlClientConnectionConfig: ConnectionConfig, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf(), - exposedSocketConnectionConfig: Socket -): DatabaseClient = - createPgPoolDatabaseClient( - vertx, vertxSqlClientConnectionConfig, extraPgConnectOptions, poolOptions, - exposedDatabaseConnectPostgreSql(exposedSocketConnectionConfig) - ) - -/** It may be more efficient to use a single shared [Database] to generate SQLs for multiple [DatabaseClient]s/[SqlClient]s. */ -fun createPgPoolDatabaseClient( - vertx: Vertx?, - vertxSqlClientConnectionType: ConnectionType, localConnectionConfig: LocalConnectionConfig, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf(), - exposedDatabase: Database? = null -) = - with(localConnectionConfig) { - val connectionConfig = when (vertxSqlClientConnectionType) { - ConnectionType.Socket -> socketConnectionConfig - ConnectionType.UnixDomainSocketWithPeerAuthentication -> unixDomainSocketWithPeerAuthenticationConnectionConfig - } - - if (exposedDatabase === null) - createPgPoolDatabaseClient( - vertx, connectionConfig, extraPgConnectOptions, poolOptions, socketConnectionConfig - ) - else - createPgPoolDatabaseClient( - vertx, connectionConfig, extraPgConnectOptions, poolOptions, exposedDatabase - ) - } - -fun createBetterPgPoolDatabaseClient( - vertx: Vertx?, - localConnectionConfig: LocalConnectionConfig, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf(), - exposedDatabase: Database? = null -) = - createPgPoolDatabaseClient( - vertx, - if (isCurrentOsLinux()) ConnectionType.UnixDomainSocketWithPeerAuthentication else ConnectionType.Socket, - localConnectionConfig, - extraPgConnectOptions, poolOptions, - exposedDatabase - ) diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt similarity index 78% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt rename to core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt index fae1efb..fcb66e2 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/EvscConfig.kt @@ -6,8 +6,9 @@ interface IEvscConfig { val vertxSqlClientConnectionConfig: ConnectionConfig } +// TODO add a type parameter for `exposedConnectionConfig` to better support RDBMSs that don't support Unix domain sockets /** - * This API is not used in the factory function parameter types yet. TODO + * This API is not used in the factory function parameter types yet. */ @ExperimentalEvscApi class EvscConfig( diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt similarity index 77% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt rename to core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt index a63caa0..668e4c0 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi.kt @@ -2,7 +2,7 @@ package com.huanshankeji.exposedvertxsqlclient import kotlin.annotation.AnnotationTarget.* -@RequiresOptIn("This API is experimental in the Exposed Vert.x SQL Client library.", RequiresOptIn.Level.WARNING) +@RequiresOptIn("This API is experimental. It may be changed in the future without notice.", RequiresOptIn.Level.WARNING) @Retention(AnnotationRetention.BINARY) // The ones commented out are what I think may be used in very few use cases. @Target( diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/InternalApi.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/InternalApi.kt new file mode 100644 index 0000000..cbe7d6d --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/InternalApi.kt @@ -0,0 +1,5 @@ +package com.huanshankeji.exposedvertxsqlclient + +@RequiresOptIn("This API is internal in the Exposed Vert.x SQL Client library. It may be changed in the future without notice.") +@Retention(AnnotationRetention.BINARY) +annotation class InternalApi \ No newline at end of file diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/exposed/ExposedDatabases.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/exposed/ExposedDatabases.kt new file mode 100644 index 0000000..c9c4b92 --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/exposed/ExposedDatabases.kt @@ -0,0 +1,35 @@ +package com.huanshankeji.exposedvertxsqlclient.exposed + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.exposedvertxsqlclient.jdbc.jdbcUrl +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.DatabaseConfig +import org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager +import org.jetbrains.exposed.sql.transactions.TransactionManager +import java.sql.Connection + +/** + * Further configurations such as [setupConnection], [databaseConfig], and [manager] are most likely not needed + * because the Exposed [Database] is mostly only used for table creation and SQL generation. + */ +@ExperimentalEvscApi +fun ConnectionConfig.Socket.exposedDatabaseConnect( + rdbms: String, + driver: String, + setupConnection: (Connection) -> Unit = {}, + databaseConfig: DatabaseConfig? = null, + manager: (Database) -> TransactionManager = { ThreadLocalTransactionManager(it) } +) = + Database.connect(jdbcUrl(rdbms), driver, user, password, setupConnection, databaseConfig, manager) + +@ExperimentalEvscApi +fun exposedDatabaseConnect( + rdbms: String, + socketConnectionConfig: ConnectionConfig.Socket, + driver: String, + setupConnection: (Connection) -> Unit = {}, + databaseConfig: DatabaseConfig? = null, + manager: (Database) -> TransactionManager = { ThreadLocalTransactionManager(it) } +) = + socketConnectionConfig.exposedDatabaseConnect(rdbms, driver, setupConnection, databaseConfig, manager) diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/jdbc/JdbcUrls.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/jdbc/JdbcUrls.kt new file mode 100644 index 0000000..be8bcdd --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/jdbc/JdbcUrls.kt @@ -0,0 +1,7 @@ +package com.huanshankeji.exposedvertxsqlclient.jdbc + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.jdbc.jdbcUrl + +fun ConnectionConfig.Socket.jdbcUrl(rdbms: String) = + jdbcUrl(rdbms, host, port, database) diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig.kt new file mode 100644 index 0000000..997c52b --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig.kt @@ -0,0 +1,45 @@ +package com.huanshankeji.exposedvertxsqlclient.local + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.ConnectionType +import com.huanshankeji.exposedvertxsqlclient.EvscConfig +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.net.LOCALHOST + +// TODO consider adding a prefix word such as "conventional" as this class is not general enough +// TODO consider refactoring this class into a function / functions to reduce the cognitive complexity +/** + * A kind of connection config that can produce both a [ConnectionConfig.Socket] and a [ConnectionConfig.UnixDomainSocketWithPeerAuthentication] + * to connect to a local database server. + */ +class LocalConnectionConfig( + val socketConnectionPort: Int? = null, + val unixDomainSocketPath: String, + val user: String, + val socketConnectionPassword: String, + val database: String +) { + companion object { + const val SOCKET_HOST = LOCALHOST + } + + val socketConnectionConfig = + ConnectionConfig.Socket(SOCKET_HOST, socketConnectionPort, user, socketConnectionPassword, database) + + val unixDomainSocketWithPeerAuthenticationConnectionConfig = + ConnectionConfig.UnixDomainSocketWithPeerAuthentication(unixDomainSocketPath, user, database) + + fun getConnectionConfig(connectionType: ConnectionType) = + when (connectionType) { + ConnectionType.Socket -> socketConnectionConfig + ConnectionType.UnixDomainSocketWithPeerAuthentication -> unixDomainSocketWithPeerAuthenticationConnectionConfig + } +} + +@ExperimentalEvscApi +fun LocalConnectionConfig.toPerformantUnixEvscConfig() = + EvscConfig(socketConnectionConfig, unixDomainSocketWithPeerAuthenticationConnectionConfig) + +@ExperimentalEvscApi +fun LocalConnectionConfig.toUniversalEvscConfig() = + EvscConfig(socketConnectionConfig, socketConnectionConfig) diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlClients.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlClients.kt new file mode 100644 index 0000000..2e79cb5 --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlClients.kt @@ -0,0 +1,98 @@ +package com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.vertx.sqlclient.setUpConventionally +import com.huanshankeji.vertx.sqlclient.withCoConnectHandler +import io.vertx.core.Future +import io.vertx.core.Vertx +import io.vertx.kotlin.coroutines.coAwait +import io.vertx.sqlclient.* + +/** + * Exposed generates prepared statements and [SqlConnectOptions.cachePreparedStatements] improves performance greatly (tested on PostgreSQL) + * so it's enabled by default. + */ +@ExperimentalEvscApi +// made inline for possible suspend calls +// TODO consider removing the default arguments so we don't forget to pass them in this library's functions +inline fun createGenericSqlClient( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + sqlConnectOptionsFromConstructor: SqlConnectOptionsT, + extraSqlConnectOptions: SqlConnectOptionsT.() -> Unit, + poolOptionsFromConstructor: PoolOptionsT, + extraPoolOptions: PoolOptionsT.() -> Unit, + noinline connectHandlerExtra: CoConnectHandler, + create: (Vertx?, SqlConnectOptionsT, PoolOptionsT, CoConnectHandler) -> SqlClientT +): SqlClientT { + val sqlConnectOptions = sqlConnectOptionsFromConstructor.apply { + setUpConventionally() + setFrom(connectionConfig) + extraSqlConnectOptions() + } + + return create(vertx, sqlConnectOptions, poolOptionsFromConstructor.apply(extraPoolOptions), connectHandlerExtra) +} + +/** + * @see createGenericSqlClient + */ +@ExperimentalEvscApi +// made not inline anymore for easier debugging +fun > createGenericSqlClientWithBuilder( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + clientBuilder: ClientBuilderT, + sqlConnectOptionsFromConstructor: SqlConnectOptionsT, + extraSqlConnectOptions: SqlConnectOptionsT.() -> Unit, + extraPoolOptions: PoolOptionsT.() -> Unit, + connectHandlerExtra: CoConnectHandler, + poolOptionsFromConstructor: PoolOptionsT +): SqlClientT = + @Suppress("NAME_SHADOWING") + createGenericSqlClient( + vertx, + connectionConfig, + sqlConnectOptionsFromConstructor, + extraSqlConnectOptions, + poolOptionsFromConstructor, + extraPoolOptions, + connectHandlerExtra + ) { vertx, database, options, connectHandlerExtra -> + clientBuilder.apply { + using(vertx) + connectingTo(database) + with(options) + val connectHandler = connectionConfig.getCoConnectHandler(connectHandlerExtra) + connectHandler?.let { withCoConnectHandler(it) } + }.build() + } + +/** + * @see createGenericSqlClient + */ +@ExperimentalEvscApi +// made not inline anymore for easier debugging +suspend fun createGenericSqlConnection( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + sqlConnectionConnect: (Vertx?, SqlConnectOptionsT) -> Future, + sqlConnectOptionsFromConstructor: SqlConnectOptionsT, + extraSqlConnectOptions: SqlConnectOptionsT.() -> Unit, + connectHandlerExtra: CoConnectHandler +): SqlConnectionT = + @Suppress("NAME_SHADOWING") + createGenericSqlClient( + vertx, + connectionConfig, + sqlConnectOptionsFromConstructor, + extraSqlConnectOptions, + null, + {}, + connectHandlerExtra + ) { vertx, database, _, connectHandlerExtra -> + sqlConnectionConnect(vertx, database).coAwait().also { + connectionConfig.initConnection(it, connectHandlerExtra) + } + } diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectOptions.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectOptions.kt new file mode 100644 index 0000000..59384a0 --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectOptions.kt @@ -0,0 +1,24 @@ +package com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import io.vertx.sqlclient.SqlConnectOptions + +fun SqlConnectOptions.setFrom(connectionConfig: ConnectionConfig.Socket) { + host = connectionConfig.host + connectionConfig.port?.let { port = it } + database = connectionConfig.database + user = connectionConfig.user + password = connectionConfig.password +} + +fun SqlConnectOptions.setFrom(connectionConfig: ConnectionConfig.UnixDomainSocketWithPeerAuthentication) { + host = connectionConfig.path + database = connectionConfig.database + user = System.getProperty("user.name") +} + +fun SqlConnectOptions.setFrom(connectionConfig: ConnectionConfig) = + when (connectionConfig) { + is ConnectionConfig.Socket -> setFrom(connectionConfig) + is ConnectionConfig.UnixDomainSocketWithPeerAuthentication -> setFrom(connectionConfig) + } diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnection.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnection.kt new file mode 100644 index 0000000..1b4983d --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnection.kt @@ -0,0 +1,12 @@ +package com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient + +import com.huanshankeji.ExperimentalApi +import io.vertx.kotlin.coroutines.coAwait +import io.vertx.sqlclient.SqlConnection + +// TODO consider using prepared statements +// TODO assert and return `Unit` +// TODO consider moving to "kotlin-common" +@ExperimentalApi +suspend fun SqlConnection.setRole(role: String) = + query("SET ROLE $role").execute().coAwait() diff --git a/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectionInitialization.kt b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectionInitialization.kt new file mode 100644 index 0000000..c228c6a --- /dev/null +++ b/core/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/vertx/sqlclient/SqlConnectionInitialization.kt @@ -0,0 +1,32 @@ +package com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import io.vertx.sqlclient.SqlConnection + +/** + * Extra initialization on [SqlConnection] in addition to [setRole] for [ConnectionConfig.UnixDomainSocketWithPeerAuthentication]. + */ +typealias CoConnectHandler = (suspend (SqlConnection) -> Unit)? +typealias ExtensionCoConnectHandler = (suspend SqlConnection.() -> Unit)? + +fun ExtensionCoConnectHandler.toWithParameterFunction(): CoConnectHandler = + this + +suspend fun ConnectionConfig.initConnection(sqlConnection: SqlConnection, extra: CoConnectHandler) { + when (this) { + is ConnectionConfig.Socket -> Unit // do nothing + is ConnectionConfig.UnixDomainSocketWithPeerAuthentication -> sqlConnection.setRole(role) + } + extra?.let { it(sqlConnection) } +} + +fun ConnectionConfig.getCoConnectHandler(extra: CoConnectHandler): CoConnectHandler = + when (this) { + is ConnectionConfig.Socket -> extra + is ConnectionConfig.UnixDomainSocketWithPeerAuthentication -> { + { + it.setRole(role) + extra?.let { extra -> extra(it) } + } + } + } diff --git a/integrated/README.md b/integrated/README.md new file mode 100644 index 0000000..64e0db5 --- /dev/null +++ b/integrated/README.md @@ -0,0 +1,3 @@ +# The integrated module + +This module includes tests, benchmarks, and examples. diff --git a/integrated/api/exposed-vertx-sql-client-integrated.api b/integrated/api/exposed-vertx-sql-client-integrated.api new file mode 100644 index 0000000..a422a43 --- /dev/null +++ b/integrated/api/exposed-vertx-sql-client-integrated.api @@ -0,0 +1,62 @@ +public final class com/huanshankeji/exposedvertxsqlclient/Alternative { + public static final field INSTANCE Lcom/huanshankeji/exposedvertxsqlclient/Alternative; + public final fun getEvscConfig ()Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; +} + +public final class com/huanshankeji/exposedvertxsqlclient/Director { + public fun (ILjava/lang/String;)V + public final fun getDirectorId ()I + public final fun getName ()Ljava/lang/String; +} + +public final class com/huanshankeji/exposedvertxsqlclient/Directors : org/jetbrains/exposed/dao/id/IntIdTable { + public static final field INSTANCE Lcom/huanshankeji/exposedvertxsqlclient/Directors; + public final fun getDirectorId ()Lorg/jetbrains/exposed/sql/Column; + public final fun getName ()Lorg/jetbrains/exposed/sql/Column; +} + +public final class com/huanshankeji/exposedvertxsqlclient/Examples : org/jetbrains/exposed/dao/id/IntIdTable { + public static final field INSTANCE Lcom/huanshankeji/exposedvertxsqlclient/Examples; + public final fun getName ()Lorg/jetbrains/exposed/sql/Column; +} + +public final class com/huanshankeji/exposedvertxsqlclient/ExamplesKt { + public static final fun examples (Lio/vertx/core/Vertx;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getEvscConfig ()Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; + public static final fun getTables ()[Lcom/huanshankeji/exposedvertxsqlclient/Examples; +} + +public final class com/huanshankeji/exposedvertxsqlclient/Film { + public fun (ILcom/huanshankeji/exposedvertxsqlclient/FilmDetails;)V + public final fun getFilmDetails ()Lcom/huanshankeji/exposedvertxsqlclient/FilmDetails; + public final fun getFilmId ()I +} + +public final class com/huanshankeji/exposedvertxsqlclient/FilmDetails { + public fun (ILjava/lang/String;Ljava/lang/Object;)V + public final fun getDirector ()Ljava/lang/Object; + public final fun getName ()Ljava/lang/String; + public final fun getSequelId ()I +} + +public final class com/huanshankeji/exposedvertxsqlclient/Films : org/jetbrains/exposed/dao/id/IntIdTable { + public static final field INSTANCE Lcom/huanshankeji/exposedvertxsqlclient/Films; + public final fun getDirectorId ()Lorg/jetbrains/exposed/sql/Column; + public final fun getFilmId ()Lorg/jetbrains/exposed/sql/Column; + public final fun getName ()Lorg/jetbrains/exposed/sql/Column; + public final fun getSequelId ()Lorg/jetbrains/exposed/sql/Column; +} + +public final class com/huanshankeji/exposedvertxsqlclient/Mappers { + public static final field INSTANCE Lcom/huanshankeji/exposedvertxsqlclient/Mappers; + public final fun getDirector ()Lcom/huanshankeji/exposed/datamapping/classproperty/ReflectionBasedClassPropertyDataMapper; + public final fun getFilmDetailsWithDirectorId ()Lcom/huanshankeji/exposed/datamapping/classproperty/ReflectionBasedClassPropertyDataMapper; + public final fun getFilmWithDirectorId ()Lcom/huanshankeji/exposed/datamapping/classproperty/ReflectionBasedClassPropertyDataMapper; + public final fun getFullFilm ()Lcom/huanshankeji/exposed/datamapping/classproperty/ReflectionBasedClassPropertyDataMapper; +} + +public final class com/huanshankeji/exposedvertxsqlclient/MappingExamplesKt { + public static final fun getFilmsLeftJoinDirectors ()Lorg/jetbrains/exposed/sql/Join; + public static final fun mappingExamples (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + diff --git a/integrated/build.gradle.kts b/integrated/build.gradle.kts new file mode 100644 index 0000000..4f95b3c --- /dev/null +++ b/integrated/build.gradle.kts @@ -0,0 +1,34 @@ +// TODO consider moving the code related to only Exposed or Vert.x to "kotlin-common" + +import com.huanshankeji.cpnProject + +plugins { + conventions + id("com.huanshankeji.benchmark.kotlinx-benchmark-jvm-conventions") +} + +dependencies { + with(commonDependencies.vertx) { implementation(platformStackDepchain()) } // needed + + implementation(cpnProject(project, ":core")) + implementation(cpnProject(project, ":postgresql")) + implementation(cpnProject(project, ":sql-dsl")) + implementation("com.huanshankeji:exposed-adt-mapping:${DependencyVersions.exposedAdtMapping}") + implementation(cpnProject(project, ":sql-dsl-with-mapper")) +} + +afterEvaluate { +// for the benchmarks + dependencies { + with(commonDependencies.vertx) { "benchmarksImplementation"(platformStackDepchain()) } // needed + // The benchmarks run and "check" passes but the code doesn't resolve without this dependency TODO remove if not needed one day + "benchmarksImplementation"(cpnProject(project, ":core")) + "benchmarksImplementation"(cpnProject(project, ":postgresql")) + + with(commonDependencies.testContainers) { + "benchmarksImplementation"(platformBom()) + "benchmarksImplementation"(postgreSql) + } + "benchmarksImplementation"(commonDependencies.slf4j.simple()) + } +} diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/AbstractBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/AbstractBenchmark.kt similarity index 100% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/AbstractBenchmark.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/AbstractBenchmark.kt diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/EmptyBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/EmptyBenchmark.kt similarity index 100% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/EmptyBenchmark.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/EmptyBenchmark.kt diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/PreparedSqlGenerationBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/PreparedSqlGenerationBenchmark.kt similarity index 100% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/PreparedSqlGenerationBenchmark.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/PreparedSqlGenerationBenchmark.kt diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/StatementBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/StatementBenchmark.kt similarity index 100% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/StatementBenchmark.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/StatementBenchmark.kt diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt new file mode 100644 index 0000000..858fa47 --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt @@ -0,0 +1,117 @@ +package com.huanshankeji.exposed.benchmark + +import com.huanshankeji.kotlinx.coroutines.benchmark.ParameterizedRunBlockingAwaitAsyncsBenchmark +import com.huanshankeji.kotlinx.coroutines.benchmark.RunBlockingAwaitAsyncsBenchmark +import kotlinx.benchmark.* +import kotlinx.coroutines.* +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction +import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync +import org.jetbrains.exposed.sql.transactions.transaction +import java.util.concurrent.Executors +import kotlin.concurrent.thread + +@State(Scope.Benchmark) +class TransactionBenchmark : WithContainerizedDatabaseBenchmark() { + @Benchmark + fun transaction() { + transaction(database) {} + } + + companion object { + const val `10K` = 10_000 + } + + @Benchmark + fun _10KTransactions() { + repeat(`10K`) { transaction(database) {} } + } + + @Suppress("SuspendFunctionOnCoroutineScope") + private suspend inline fun CoroutineScope.awaitAsync10K(crossinline block: () -> Unit) = + List(`10K`) { async { block() } }.awaitAll() + + @Suppress("SuspendFunctionOnCoroutineScope") + private suspend fun CoroutineScope.awaitAsync10KTransactions() = + awaitAsync10K { transaction(database) {} } + + /** + * Compare with [RunBlockingAwaitAsyncsBenchmark]. + */ + @Benchmark + fun singleThreadConcurrent10KTransactions() = + @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) + runBlocking(newSingleThreadContext("single thread")) { + awaitAsync10KTransactions() + } + + + /** + * Compare with [ParameterizedRunBlockingAwaitAsyncsBenchmark]. + */ + @Benchmark + fun multiThreadConcurrent10KTransactionsWithSharedDatabase() = + runBlocking { awaitAsync10KTransactions() } + + + @Benchmark + fun _10KSuspendedTransactions() = runBlocking { + repeat(`10K`) { newSuspendedTransaction(db = database) {} } + } + + @Benchmark + fun _10KSuspendedTransactionAsyncs() = runBlocking { + List(`10K`) { suspendedTransactionAsync(db = database) {} }.awaitAll() + } + + private fun numProcessors() = + Runtime.getRuntime().availableProcessors().also { + println("Number of processors: $it") + } + + @Benchmark + fun multiThreadMultiConnectionEach10KLocalTransactions() { + // Note that on a device with heterogeneous architecture some threads may finish earlier than others. + List(numProcessors()) { + thread { + val database = databaseConnect() + repeat(`10K`) { transaction(database) {} } + } + }.forEach { + it.join() + } + } + + + val databaseThreadLocal = ThreadLocal() + lateinit var dispatcherWithThreadLocalDatabases: ExecutorCoroutineDispatcher + + @Setup + fun setUpThreadLocalDatabases() { + dispatcherWithThreadLocalDatabases = Executors.newFixedThreadPool(numProcessors()) { + Thread { + it.run() + databaseThreadLocal.set(databaseConnect()) + } + }.asCoroutineDispatcher() + } + + @TearDown + fun teardownDispatcherWithThreadLocalDatabases() { + dispatcherWithThreadLocalDatabases.close() + } + + @Benchmark + fun multiThreadConcurrent10KTransactionsWithThreadLocalDatabases() { + runBlocking(dispatcherWithThreadLocalDatabases) { + awaitAsync10K { transaction(databaseThreadLocal.get()) {} } + } + } + + @Benchmark + fun multiThreadConcurrent10KTransactionsWithImplicitThreadLocalDatabases() { + runBlocking(dispatcherWithThreadLocalDatabases) { + awaitAsync10K { transaction {} } + } + } +} \ No newline at end of file diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt similarity index 75% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt index 9c9cb8d..51e21c7 100644 --- a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/WithContainerizedDatabaseBenchmark.kt @@ -1,7 +1,7 @@ package com.huanshankeji.exposed.benchmark import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig -import com.huanshankeji.exposedvertxsqlclient.exposedDatabaseConnectPostgreSql +import com.huanshankeji.exposedvertxsqlclient.postgresql.exposed.exposedDatabaseConnectPostgresql import kotlinx.benchmark.Scope import kotlinx.benchmark.Setup import kotlinx.benchmark.State @@ -16,9 +16,8 @@ class WithContainerizedDatabaseBenchmark : AbstractBenchmark() { lateinit var database: Database fun databaseConnect() = - exposedDatabaseConnectPostgreSql(with(postgreSQLContainer) { - ConnectionConfig.Socket(host, firstMappedPort, username, password, databaseName) - }) + with(postgreSQLContainer) { ConnectionConfig.Socket(host, firstMappedPort, username, password, databaseName) } + .exposedDatabaseConnectPostgresql() @Setup fun setUp() { diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/table/Tables.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/table/Tables.kt similarity index 100% rename from lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/table/Tables.kt rename to integrated/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/table/Tables.kt diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractBenchmark.kt new file mode 100644 index 0000000..1220fa9 --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractBenchmark.kt @@ -0,0 +1,11 @@ +package com.huanshankeji.kotlinx.coroutines.benchmark + +import kotlinx.benchmark.Measurement +import kotlinx.benchmark.Scope +import kotlinx.benchmark.State +import kotlinx.benchmark.Warmup + +@State(Scope.Benchmark) +@Warmup(time = 1, iterations = 8) // 4 seems not enough +@Measurement(time = 1, iterations = 8) +abstract class AbstractBenchmark \ No newline at end of file diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractRunBlockingAwaitAsyncsBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractRunBlockingAwaitAsyncsBenchmark.kt new file mode 100644 index 0000000..a85c4c8 --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AbstractRunBlockingAwaitAsyncsBenchmark.kt @@ -0,0 +1,7 @@ +package com.huanshankeji.kotlinx.coroutines.benchmark + +abstract class AbstractRunBlockingAwaitAsyncsBenchmark : AbstractBenchmark() { + abstract fun runBlockingAwait1mAsyncs() + + abstract fun runBlockingAwait1KAsync1mSums() +} \ No newline at end of file diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AwaitAsyncs.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AwaitAsyncs.kt new file mode 100644 index 0000000..ebebd26 --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/AwaitAsyncs.kt @@ -0,0 +1,23 @@ +package com.huanshankeji.kotlinx.coroutines.benchmark + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll + +@Suppress("SuspendFunctionOnCoroutineScope") +internal suspend inline fun CoroutineScope.await1mAsyncs() { + List(1 shl 20) { async {} }.awaitAll() +} + +internal val `1mSizeList` = List(1 shl 20) { it } + +// It seems the loop get optimized and removed in this function. +@Suppress("SuspendFunctionOnCoroutineScope") +internal suspend inline fun CoroutineScope.await1kAsync1mLoops() { + List(1 shl 10) { async { repeat(1 shl 20) {} } }.awaitAll() +} + +@Suppress("SuspendFunctionOnCoroutineScope") +internal suspend inline fun CoroutineScope.await1kAsync1mSums() { + List(1 shl 10) { async { `1mSizeList`.sum() } }.awaitAll() +} diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/ParameterizedRunBlockingAwaitAsyncsBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/ParameterizedRunBlockingAwaitAsyncsBenchmark.kt new file mode 100644 index 0000000..92239fa --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/ParameterizedRunBlockingAwaitAsyncsBenchmark.kt @@ -0,0 +1,34 @@ +package com.huanshankeji.kotlinx.coroutines.benchmark + +import kotlinx.benchmark.Benchmark +import kotlinx.benchmark.Param +import kotlinx.coroutines.* + +class ParameterizedRunBlockingAwaitAsyncsBenchmark : AbstractRunBlockingAwaitAsyncsBenchmark() { + enum class DispatcherArgumentEnum { + Default, /*Main,*/ Unconfined, IO, SingleThread + } + + @Param + lateinit var dispatcherArgumentEnum: DispatcherArgumentEnum + + @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) + val singleThreadContext = newSingleThreadContext("single thread") + val dispatcher + get() = when (dispatcherArgumentEnum) { + DispatcherArgumentEnum.Default -> Dispatchers.Default + //DispatcherArgumentEnum.Main -> Dispatchers.Main + DispatcherArgumentEnum.Unconfined -> Dispatchers.Unconfined + DispatcherArgumentEnum.IO -> Dispatchers.IO + DispatcherArgumentEnum.SingleThread -> singleThreadContext + } + + + @Benchmark + override fun runBlockingAwait1mAsyncs() = + runBlocking(dispatcher) { await1mAsyncs() } + + @Benchmark + override fun runBlockingAwait1KAsync1mSums() = + runBlocking(dispatcher) { await1kAsync1mSums() } +} \ No newline at end of file diff --git a/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/RunBlockingAwaitAsyncsBenchmark.kt b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/RunBlockingAwaitAsyncsBenchmark.kt new file mode 100644 index 0000000..f0608ce --- /dev/null +++ b/integrated/src/benchmarks/kotlin/com/huanshankeji/kotlinx/coroutines/benchmark/RunBlockingAwaitAsyncsBenchmark.kt @@ -0,0 +1,14 @@ +package com.huanshankeji.kotlinx.coroutines.benchmark + +import kotlinx.benchmark.Benchmark +import kotlinx.coroutines.runBlocking + +class RunBlockingAwaitAsyncsBenchmark : AbstractRunBlockingAwaitAsyncsBenchmark() { + @Benchmark + override fun runBlockingAwait1mAsyncs() = + runBlocking { await1mAsyncs() } + + @Benchmark + override fun runBlockingAwait1KAsync1mSums() = + runBlocking { await1kAsync1mSums() } +} \ No newline at end of file diff --git a/lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt b/integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt similarity index 59% rename from lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt rename to integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt index d87ca02..f0450e1 100644 --- a/lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt +++ b/integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/Examples.kt @@ -1,15 +1,22 @@ +@file:OptIn(ExperimentalEvscApi::class) + package com.huanshankeji.exposedvertxsqlclient import com.huanshankeji.exposed.* +import com.huanshankeji.exposedvertxsqlclient.local.toPerformantUnixEvscConfig +import com.huanshankeji.exposedvertxsqlclient.postgresql.exposed.exposedDatabaseConnectPostgresql +import com.huanshankeji.exposedvertxsqlclient.postgresql.local.defaultPostgresqlLocalConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.postgresql.vertx.pgclient.createPgClient +import com.huanshankeji.exposedvertxsqlclient.postgresql.vertx.pgclient.createPgPool import com.huanshankeji.exposedvertxsqlclient.sql.* -import com.huanshankeji.exposedvertxsqlclient.sql.mapping.deleteIgnoreWhere -import com.huanshankeji.exposedvertxsqlclient.sql.mapping.deleteWhere +import io.vertx.core.Verticle import io.vertx.core.Vertx -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import io.vertx.sqlclient.SqlClient import org.jetbrains.exposed.dao.id.IntIdTable +import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq +import org.jetbrains.exposed.sql.exists import org.jetbrains.exposed.sql.selectAll object Examples : IntIdTable("examples") { @@ -18,19 +25,34 @@ object Examples : IntIdTable("examples") { val tables = arrayOf(Examples) +val evscConfig = ConnectionConfig.Socket("localhost", user = "user", password = "password", database = "database") + .toUniversalEvscConfig() + +object Alternative { + // Unix domain socket alternative + val evscConfig = defaultPostgresqlLocalConnectionConfig( + user = "user", + socketConnectionPassword = "password", + database = "database" + ).toPerformantUnixEvscConfig() +} + @OptIn(ExperimentalEvscApi::class) suspend fun examples(vertx: Vertx) { - val socketConnectionConfig = - ConnectionConfig.Socket("localhost", user = "user", password = "password", database = "database") - val exposedDatabase = exposedDatabaseConnectPostgreSql(socketConnectionConfig) - val databaseClient = createPgPoolDatabaseClient( - vertx, socketConnectionConfig, exposedDatabase = exposedDatabase - ) - - withContext(Dispatchers.IO) { - databaseClient.exposedTransaction { - SchemaUtils.create(*tables) - } + /** It may be more efficient to reuse a single shared [Database] to generate SQLs in multiple [DatabaseClient]s for [SqlClient]s in respective [Verticle]s. */ + val exposedDatabase = evscConfig.exposedConnectionConfig.exposedDatabaseConnectPostgresql() + + val sqlClient = createPgClient(vertx, evscConfig.vertxSqlClientConnectionConfig) + val pool = createPgPool(vertx, evscConfig.vertxSqlClientConnectionConfig) + val sqlConnection = createPgClient(vertx, evscConfig.vertxSqlClientConnectionConfig) + + val vertxSqlClient = sqlClient + + val databaseClient = DatabaseClient(vertxSqlClient, exposedDatabase) + + // put in `Vertx.executeBlocking` or `Dispatchers.IO` if needed + databaseClient.exposedTransaction { + SchemaUtils.create(*tables) } run { @@ -66,7 +88,9 @@ suspend fun examples(vertx: Vertx) { databaseClient.select(Examples) { select(Examples.name).where(Examples.id eq 1) }.single()[Examples.name] // This function still depends on the old SELECT DSL and will be updated. val exampleName2 = - databaseClient.selectSingleColumn(Examples, Examples.name) { selectAll().where(Examples.id eq 2) }.single() + databaseClient.selectSingleColumn(Examples, Examples.name) { where(Examples.id eq 2) }.single() + + val examplesExist = databaseClient.selectExpression(exists(Examples.selectAll())) val deleteRowCount1 = databaseClient.deleteWhere(Examples) { id eq 1 } assert(deleteRowCount1 == 1) diff --git a/lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt b/integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt similarity index 88% rename from lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt rename to integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt index 4daca30..24dac9b 100644 --- a/lib/src/test/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt +++ b/integrated/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/MappingExamples.kt @@ -2,12 +2,11 @@ package com.huanshankeji.exposedvertxsqlclient import com.huanshankeji.exposed.datamapping.classproperty.PropertyColumnMappingConfig import com.huanshankeji.exposed.datamapping.classproperty.reflectionBasedClassPropertyDataMapper -import com.huanshankeji.exposedvertxsqlclient.sql.mapping.insert -import com.huanshankeji.exposedvertxsqlclient.sql.mapping.select +import com.huanshankeji.exposedvertxsqlclient.sql.mapping.insertWithMapper +import com.huanshankeji.exposedvertxsqlclient.sql.mapping.selectWithMapper import io.vertx.sqlclient.Pool import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.SqlExpressionBuilder.inList -import org.jetbrains.exposed.sql.select // copied and adapted from https://github.com/huanshankeji/exposed-adt-mapping/blob/main/lib/src/test/kotlin/com/huanshankeji/exposed/datamapping/classproperty/Examples.kt // Update accordingly to keep the code consistent. @@ -84,18 +83,18 @@ object Mappers { suspend fun mappingExamples(databaseClient: DatabaseClient) { val directorId = 1 val director = Director(directorId, "George Lucas") - databaseClient.insert(Directors, director, Mappers.director) + databaseClient.insertWithMapper(Directors, director, Mappers.director) val episodeIFilmDetails = FilmDetails(1, "Star Wars: Episode I – The Phantom Menace", directorId) // insert without the ID since it's `AUTO_INCREMENT` - databaseClient.insert(Films, episodeIFilmDetails, Mappers.filmDetailsWithDirectorId) + databaseClient.insertWithMapper(Films, episodeIFilmDetails, Mappers.filmDetailsWithDirectorId) val filmId = 2 val episodeIIFilmDetails = FilmDetails(2, "Star Wars: Episode II – Attack of the Clones", directorId) val filmWithDirectorId = FilmWithDirectorId(filmId, episodeIIFilmDetails) - databaseClient.insert(Films, filmWithDirectorId, Mappers.filmWithDirectorId) // insert with the ID + databaseClient.insertWithMapper(Films, filmWithDirectorId, Mappers.filmWithDirectorId) // insert with the ID - val fullFilms = databaseClient.select(filmsLeftJoinDirectors, Mappers.fullFilm) { - select(Films.filmId inList listOf(1, 2)) // This API still depends on the old SELECT DSL and will be refactored. + val fullFilms = databaseClient.selectWithMapper(filmsLeftJoinDirectors, Mappers.fullFilm) { + where(Films.filmId inList listOf(1, 2)) // This API still depends on the old SELECT DSL and will be refactored. } } diff --git a/lib/api/exposed-vertx-sql-client-postgresql.api b/lib/api/exposed-vertx-sql-client-postgresql.api deleted file mode 100644 index e1da900..0000000 --- a/lib/api/exposed-vertx-sql-client-postgresql.api +++ /dev/null @@ -1,227 +0,0 @@ -public abstract interface class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { - public abstract fun getDatabase ()Ljava/lang/String; - public abstract fun getUserAndRole ()Ljava/lang/String; -} - -public final class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket : com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { - public fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public synthetic fun (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun getDatabase ()Ljava/lang/String; - public final fun getHost ()Ljava/lang/String; - public final fun getPassword ()Ljava/lang/String; - public final fun getPort ()Ljava/lang/Integer; - public final fun getUser ()Ljava/lang/String; - public fun getUserAndRole ()Ljava/lang/String; -} - -public final class com/huanshankeji/exposedvertxsqlclient/ConnectionConfig$UnixDomainSocketWithPeerAuthentication : com/huanshankeji/exposedvertxsqlclient/ConnectionConfig { - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public fun getDatabase ()Ljava/lang/String; - public final fun getPath ()Ljava/lang/String; - public final fun getRole ()Ljava/lang/String; - public fun getUserAndRole ()Ljava/lang/String; -} - -public final class com/huanshankeji/exposedvertxsqlclient/ConnectionType : java/lang/Enum { - public static final field Socket Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; - public static final field UnixDomainSocketWithPeerAuthentication Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; - public static fun values ()[Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType; -} - -public final class com/huanshankeji/exposedvertxsqlclient/DatabaseClient { - public fun (Lio/vertx/sqlclient/SqlClient;Lorg/jetbrains/exposed/sql/Database;ZZ)V - public synthetic fun (Lio/vertx/sqlclient/SqlClient;Lorg/jetbrains/exposed/sql/Database;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun close (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun createTable (Lorg/jetbrains/exposed/sql/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun doExecute (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun dropTable (Lorg/jetbrains/exposed/sql/Table;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun execute (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeBatch (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeBatchForVertxSqlClientRowSetSequence (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeBatchQuery (Lorg/jetbrains/exposed/sql/FieldSet;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeBatchQuery (Lorg/jetbrains/exposed/sql/FieldSet;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeBatchUpdate (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeExpression (Lkotlin/reflect/KClass;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeForVertxSqlClientRowSet (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executePlainSql (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executePlainSqlUpdate (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeQuery (Lorg/jetbrains/exposed/sql/Query;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeQuery (Lorg/jetbrains/exposed/sql/Query;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeSingleOrNoUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeSingleUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeUpdate (Lorg/jetbrains/exposed/sql/statements/Statement;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun executeWithMapping (Lorg/jetbrains/exposed/sql/statements/Statement;Ljava/util/function/Function;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun exposedTransaction (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun getExposedDatabase ()Lorg/jetbrains/exposed/sql/Database; - public final fun getFieldExpressionSetWithTransaction (Lorg/jetbrains/exposed/sql/FieldSet;)Ljava/util/Set; - public final fun getFieldExpressionSetWithTransaction (Lorg/jetbrains/exposed/sql/Query;)Ljava/util/Set; - public final fun getLogSql ()Z - public final fun getValidateBatch ()Z - public final fun getVertxSqlClient ()Lio/vertx/sqlclient/SqlClient; - public final fun isWorking (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun toExposedResultRowWithTransaction (Lio/vertx/sqlclient/Row;Lorg/jetbrains/exposed/sql/Query;)Lorg/jetbrains/exposed/sql/ResultRow; -} - -public final class com/huanshankeji/exposedvertxsqlclient/DatabaseClientKt { - public static final fun createBetterPgPoolDatabaseClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static synthetic fun createBetterPgPoolDatabaseClient$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;ILjava/lang/Object;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static final fun createPgPoolDatabaseClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static final fun createPgPoolDatabaseClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static final fun createPgPoolDatabaseClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType;Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static synthetic fun createPgPoolDatabaseClient$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;ILjava/lang/Object;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static synthetic fun createPgPoolDatabaseClient$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;ILjava/lang/Object;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static synthetic fun createPgPoolDatabaseClient$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionType;Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lorg/jetbrains/exposed/sql/Database;ILjava/lang/Object;)Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient; - public static final fun getFieldExpressionSet (Lorg/jetbrains/exposed/sql/FieldSet;)Ljava/util/Set; - public static final fun getFieldExpressionSet (Lorg/jetbrains/exposed/sql/Query;)Ljava/util/Set; - public static final fun getSavepointNameRegex ()Lkotlin/text/Regex; - public static final fun getVertxPgClientPreparedSql (Lorg/jetbrains/exposed/sql/statements/Statement;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; - public static final fun getVertxSqlClientArgTuple (Lorg/jetbrains/exposed/sql/statements/Statement;)Lio/vertx/sqlclient/Tuple; - public static final fun singleOrNoResult (Lio/vertx/sqlclient/RowSet;)Ljava/lang/Object; - public static final fun singleOrNoUpdate (I)Z - public static final fun singleResult (Lio/vertx/sqlclient/RowSet;)Ljava/lang/Object; - public static final fun singleStatementArguments (Lorg/jetbrains/exposed/sql/statements/Statement;)Ljava/lang/Iterable; - public static final fun toExposedResultRow (Lio/vertx/sqlclient/Row;Ljava/util/Set;)Lorg/jetbrains/exposed/sql/ResultRow; - public static final fun toExposedResultRow (Lio/vertx/sqlclient/Row;Lorg/jetbrains/exposed/sql/Query;)Lorg/jetbrains/exposed/sql/ResultRow; - public static final fun toVertxPgClientPreparedSql (Ljava/lang/String;)Ljava/lang/String; - public static final fun toVertxTuple (Ljava/lang/Iterable;)Lio/vertx/sqlclient/Tuple; - public static final fun types (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun withPgTransaction (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withSavepointAndRollbackIfThrows (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withSavepointAndRollbackIfThrowsOrFalse (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withSavepointAndRollbackIfThrowsOrLeft (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withSavepointAndRollbackIfThrowsOrNone (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withTransaction (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun withTransactionCommitOrRollback (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class com/huanshankeji/exposedvertxsqlclient/EvscConfig : com/huanshankeji/exposedvertxsqlclient/IEvscConfig { - public fun (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;)V - public fun getExposedConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; - public fun getVertxSqlClientConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig; -} - -public abstract interface annotation class com/huanshankeji/exposedvertxsqlclient/ExperimentalEvscApi : java/lang/annotation/Annotation { -} - -public final class com/huanshankeji/exposedvertxsqlclient/ExposedDatabasesKt { - public static final fun exposedDatabaseConnectPostgreSql (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;)Lorg/jetbrains/exposed/sql/Database; -} - -public abstract interface class com/huanshankeji/exposedvertxsqlclient/IEvscConfig { - public abstract fun getExposedConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; - public abstract fun getVertxSqlClientConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig; -} - -public final class com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig { - public static final field Companion Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig$Companion; - public static final field SOCKET_HOST Ljava/lang/String; - public static final field UNIX_DOMAIN_SOCKET_PATH Ljava/lang/String; - public fun (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V - public final fun getDatabase ()Ljava/lang/String; - public final fun getSocketConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket; - public final fun getSocketConnectionPassword ()Ljava/lang/String; - public final fun getUnixDomainSocketWithPeerAuthenticationConnectionConfig ()Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$UnixDomainSocketWithPeerAuthentication; - public final fun getUser ()Ljava/lang/String; -} - -public final class com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig$Companion { -} - -public final class com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfigKt { - public static final fun toPerformantUnixEvscConfig (Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;)Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; - public static final fun toUniversalEvscConfig (Lcom/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig;)Lcom/huanshankeji/exposedvertxsqlclient/EvscConfig; -} - -public final class com/huanshankeji/exposedvertxsqlclient/SingleUpdateException : java/lang/Exception { - public fun (I)V -} - -public final class com/huanshankeji/exposedvertxsqlclient/VertxSqlClientsKt { - public static final fun createPeerAuthenticationUnixDomainSocketGenericPgClient (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static synthetic fun createPeerAuthenticationUnixDomainSocketGenericPgClient$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun createPeerAuthenticationUnixDomainSocketPgConnectionAndSetRole (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun createPeerAuthenticationUnixDomainSocketPgConnectionAndSetRole$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun createPeerAuthenticationUnixDomainSocketPgPool (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/pgclient/PgPool; - public static synthetic fun createPeerAuthenticationUnixDomainSocketPgPool$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;ILjava/lang/Object;)Lio/vertx/pgclient/PgPool; - public static final fun createPeerAuthenticationUnixDomainSocketPgPoolAndSetRole (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/pgclient/PgPool; - public static synthetic fun createPeerAuthenticationUnixDomainSocketPgPoolAndSetRole$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;ILjava/lang/Object;)Lio/vertx/pgclient/PgPool; - public static final fun createPeerAuthenticationUnixDomainSocketPgSqlClient (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/sqlclient/SqlClient; - public static synthetic fun createPeerAuthenticationUnixDomainSocketPgSqlClient$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;ILjava/lang/Object;)Lio/vertx/sqlclient/SqlClient; - public static final fun createPgConnectOptions (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lio/vertx/pgclient/PgConnectOptions; - public static synthetic fun createPgConnectOptions$default (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/vertx/pgclient/PgConnectOptions; - public static final fun createSocketGenericPgClient (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static synthetic fun createSocketGenericPgClient$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun createSocketPgConnection (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun createSocketPgConnection$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun createSocketPgPool (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/pgclient/PgPool; - public static synthetic fun createSocketPgPool$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;ILjava/lang/Object;)Lio/vertx/pgclient/PgPool; - public static final fun createSocketPgSqlClient (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;)Lio/vertx/sqlclient/SqlClient; - public static synthetic fun createSocketPgSqlClient$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;ILjava/lang/Object;)Lio/vertx/sqlclient/SqlClient; - public static final fun createUnixDomainSocketPgSqlClientAndSetRole (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun createUnixDomainSocketPgSqlClientAndSetRole$default (Lio/vertx/core/Vertx;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;Lio/vertx/sqlclient/PoolOptions;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun executeSetRole (Lio/vertx/sqlclient/SqlConnection;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ReflectionBasedClassPropertyIndexVertxSqlClientRowDataQueryMapper : com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper { - public fun (Lkotlin/reflect/KClass;Lkotlin/Unit;)V - public final fun getClassPropertyColumnIndexMappings ()Lkotlin/Unit; - public final fun getClazz ()Lkotlin/reflect/KClass; - public fun rowToData (Lio/vertx/sqlclient/Row;)Ljava/lang/Object; -} - -public final class com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSqlKt { - public static final fun batchInsert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun batchInsertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun batchInsertSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun batchSingleOrNoUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun batchSingleOrNoUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun batchUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun batchUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun executeInsertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun executeSingleColumnSelectQuery (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun executeSingleColumnSelectQuery (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insertIgnoreSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun insertIgnoreSelect$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun insertIgnoreSingle (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insertSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun insertSelect$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun insertSingle (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun select (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun select (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectBatch (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/FieldSet;Lkotlin/jvm/functions/Function2;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectExpression (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/reflect/KClass;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectSingleColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectSingleColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectSingleEntityIdColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun selectTableExpression (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun sortDataAndBatchUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun sortDataAndBatchUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun update (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun update$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; -} - -public final class com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapperKt { - public static final fun batchInsert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun batchInsertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun batchUpdateBuilderSetter (Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;)Lkotlin/jvm/functions/Function3; - public static final fun deleteIgnoreWhere (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun deleteIgnoreWhere$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun deleteWhere (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun deleteWhere$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun executeQuery (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Query;Lcom/huanshankeji/exposed/datamapping/DataQueryMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun executeVertxSqlClientRowQuery (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Query;Lcom/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun insertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun select (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lcom/huanshankeji/exposed/datamapping/DataQueryMapper;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun update (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun update$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; -} - -public abstract interface class com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper { - public abstract fun rowToData (Lio/vertx/sqlclient/Row;)Ljava/lang/Object; -} - diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts deleted file mode 100644 index 2a61c1c..0000000 --- a/lib/build.gradle.kts +++ /dev/null @@ -1,53 +0,0 @@ -plugins { - conventions - id("com.huanshankeji.benchmark.kotlinx-benchmark-jvm-conventions") - id("org.jetbrains.dokka") -} - -dependencies { - api(commonDependencies.exposed.core()) // TODO: use `implementation` when possible - // TODO: remove the Exposed JDBC dependency and the PostgresSQL dependency when there is no need to to generate SQLs with an Exposed transaction - runtimeOnly(commonDependencies.exposed.module("jdbc")) - api(commonDependencies.kotlinCommon.exposed()) - implementation("com.huanshankeji:exposed-adt-mapping:${DependencyVersions.exposedAdtMapping}") - - with(commonDependencies.vertx) { - implementation(platformStackDepchain()) - api(moduleWithoutVersion("sql-client")) // TODO: use `implementation` when possible - implementation(moduleWithoutVersion("lang-kotlin")) - implementation(moduleWithoutVersion("lang-kotlin-coroutines")) - } - implementation(commonDependencies.kotlinCommon.vertx()) - - implementation(commonDependencies.kotlinCommon.core()) - implementation(commonDependencies.arrow.core()) - - implementation(commonDependencies.kotlinCommon.net()) -} - - -// for PostgreSQL -dependencies { - runtimeOnly(commonDependencies.postgreSql()) - implementation(commonDependencies.vertx.moduleWithoutVersion("pg-client")) -} - -afterEvaluate { -// for the benchmarks - dependencies { - with(commonDependencies.testContainers) { - "benchmarksImplementation"(platformBom()) - "benchmarksImplementation"(postgreSql) - } - "benchmarksImplementation"(commonDependencies.slf4j.simple()) - } -} - -dokka { - dokkaSourceSets.all { - sourceLink { - remoteUrl("https://github.com/huanshankeji/exposed-vertx-sql-client/tree/v${version}/lib") - remoteLineSuffix.set("#L") - } - } -} diff --git a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt b/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt deleted file mode 100644 index 928295c..0000000 --- a/lib/src/benchmarks/kotlin/com/huanshankeji/exposed/benchmark/TransactionBenchmark.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.huanshankeji.exposed.benchmark - -import com.huanshankeji.kotlinx.coroutine.awaitAny -import kotlinx.benchmark.Benchmark -import kotlinx.benchmark.Scope -import kotlinx.benchmark.State -import kotlinx.coroutines.* -import org.jetbrains.exposed.sql.transactions.experimental.newSuspendedTransaction -import org.jetbrains.exposed.sql.transactions.experimental.suspendedTransactionAsync -import org.jetbrains.exposed.sql.transactions.transaction -import kotlin.concurrent.thread - -@State(Scope.Benchmark) -class TransactionBenchmark : WithContainerizedDatabaseBenchmark() { - @Benchmark - fun transaction() { - transaction(database) {} - } - - companion object { - const val `10K` = 10_000 - } - - @Benchmark - fun _10KTransactions() { - repeat(`10K`) { transaction(database) {} } - } - - private suspend fun awaitAsync10KTransactions() = - coroutineScope { - List(`10K`) { async { transaction(database) {} } }.awaitAll() - } - - @Benchmark - fun singleThreadConcurrent10KTransactions() = runBlocking { - awaitAsync10KTransactions() - } - - - @Benchmark - fun multiThreadConcurrent10KTransactions() = runBlocking { - withContext(Dispatchers.Default) { - awaitAsync10KTransactions() - } - } - - - @Benchmark - fun _10KSuspendedTransactions() = runBlocking { - repeat(`10K`) { newSuspendedTransaction(db = database) {} } - } - - @Benchmark - fun _10KSuspendedTransactionAsyncs() = runBlocking { - List(`10K`) { suspendedTransactionAsync(db = database) {} }.awaitAny() - } - - @Benchmark - fun multiThreadMultiConnectionEach10KLocalTransactions() { - List(Runtime.getRuntime().availableProcessors()) { - thread { - val database = databaseConnect() - repeat(`10K`) { transaction(database) {} } - } - }.forEach { - it.join() - } - } -} \ No newline at end of file diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExposedDatabases.kt b/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExposedDatabases.kt deleted file mode 100644 index 85dd82a..0000000 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/ExposedDatabases.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.huanshankeji.exposedvertxsqlclient - -import org.jetbrains.exposed.sql.Database - -fun exposedDatabaseConnectPostgreSql(socketConnectionConfig: ConnectionConfig.Socket) = - with(socketConnectionConfig) { - Database.connect( - "jdbc:postgresql://$host${port?.let { ":$it" } ?: ""}/$database", - "org.postgresql.Driver", - user = user, - password = password - ) - } diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig.kt b/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig.kt deleted file mode 100644 index dbfd61c..0000000 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/LocalConnectionConfig.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.huanshankeji.exposedvertxsqlclient - -import com.huanshankeji.net.LOCALHOST - -// TODO: move to a separate package and consider adding a prefix word such as "default" or "conventional" as this class is not general enough -/** - * A kind of connection config that can produce both a [ConnectionConfig.Socket] and a [ConnectionConfig.UnixDomainSocketWithPeerAuthentication] - * to connect to a local database server. - */ -class LocalConnectionConfig(val database: String, val user: String, val socketConnectionPassword: String) { - companion object { - const val UNIX_DOMAIN_SOCKET_PATH = "/var/run/postgresql" - const val SOCKET_HOST = LOCALHOST - } - - val socketConnectionConfig = - ConnectionConfig.Socket(SOCKET_HOST, null, user, socketConnectionPassword, database) - - val unixDomainSocketWithPeerAuthenticationConnectionConfig = - ConnectionConfig.UnixDomainSocketWithPeerAuthentication(UNIX_DOMAIN_SOCKET_PATH, user, database) -} - -@ExperimentalEvscApi -fun LocalConnectionConfig.toPerformantUnixEvscConfig() = - EvscConfig(socketConnectionConfig, unixDomainSocketWithPeerAuthenticationConnectionConfig) - -@ExperimentalEvscApi -fun LocalConnectionConfig.toUniversalEvscConfig() = - EvscConfig(socketConnectionConfig, socketConnectionConfig) diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/VertxSqlClients.kt b/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/VertxSqlClients.kt deleted file mode 100644 index 6ec1cc3..0000000 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/VertxSqlClients.kt +++ /dev/null @@ -1,163 +0,0 @@ -package com.huanshankeji.exposedvertxsqlclient - -import com.huanshankeji.Untested -import io.vertx.core.Vertx -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.Pool -import io.vertx.sqlclient.PoolOptions -import io.vertx.sqlclient.SqlClient -import io.vertx.sqlclient.SqlConnection -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch - -@PublishedApi -internal inline fun createPgConnectOptions( - mainPgConnectOptions: PgConnectOptions.() -> Unit = {}, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, -): PgConnectOptions = - PgConnectOptions().apply { - cachePreparedStatements = true // This improves performance greatly so it's enabled by default. - mainPgConnectOptions() - extraPgConnectOptions() - } - -/* -// An extracted common `create` argument for `PgConnection`, but a suspend function has an incompatible type. -private val pgConnectionConnect: suspend (Vertx?, PgConnectOptions, Nothing?) -> PgConnection = { vertx, pgConnectOptions, _ -> - PgConnection.connect(vertx, pgConnectOptions).await() -} -*/ - -suspend fun SqlConnection.executeSetRole(role: String) = - query("SET ROLE $role").execute().coAwait() - -// TODO: use `ConnectionConfig` as the argument directly in all the following functions - -inline fun createSocketGenericPgClient( - vertx: Vertx?, - host: String, port: Int?, database: String, user: String, password: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptionsT, - create: (Vertx?, PgConnectOptions, PoolOptionsT) -> Client -): Client { - val pgConnectOptions = createPgConnectOptions({ - this.host = host - port?.let { this.port = it } - this.database = database - this.user = user - this.password = password - }, extraPgConnectOptions) - - return create(vertx, pgConnectOptions, poolOptions) -} - -fun createSocketPgSqlClient( - vertx: Vertx?, - host: String, port: Int?, database: String, user: String, password: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): SqlClient = - createSocketGenericPgClient( - vertx, host, port, database, user, password, extraPgConnectOptions, poolOptions, PgPool::client - ) - -fun createSocketPgPool( - vertx: Vertx?, - host: String, port: Int?, database: String, user: String, password: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): PgPool = - createSocketGenericPgClient( - vertx, host, port, database, user, password, extraPgConnectOptions, poolOptions, PgPool::pool - ) - -@Untested -suspend fun createSocketPgConnection( - vertx: Vertx?, - host: String, port: Int?, database: String, user: String, password: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {} -): PgConnection = - createSocketGenericPgClient( - vertx, host, port, database, user, password, extraPgConnectOptions, null - ) { vertx, pgConnectOptions, _ -> - PgConnection.connect(vertx, pgConnectOptions).coAwait() - } - - -inline fun createPeerAuthenticationUnixDomainSocketGenericPgClient( - vertx: Vertx?, - unixDomainSocketPath: String, database: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptionsT, - create: (Vertx?, PgConnectOptions, PoolOptionsT) -> Client -): Client { - val pgConnectOptions = createPgConnectOptions( - { - host = unixDomainSocketPath - this.database = database - user = System.getProperty("user.name") - }, extraPgConnectOptions - ) - - return create(vertx, pgConnectOptions, poolOptions) -} - -fun createPeerAuthenticationUnixDomainSocketPgSqlClient( - vertx: Vertx?, - unixDomainSocketPath: String, database: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): SqlClient = - createPeerAuthenticationUnixDomainSocketGenericPgClient( - vertx, unixDomainSocketPath, database, extraPgConnectOptions, poolOptions, PgPool::client - ) - -suspend fun createUnixDomainSocketPgSqlClientAndSetRole( - vertx: Vertx?, - host: String, database: String, role: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): SqlClient = - createPeerAuthenticationUnixDomainSocketPgSqlClient( - vertx, host, database, extraPgConnectOptions, poolOptions - ).apply { - // Is this done for all connections? - query("SET ROLE $role").execute().coAwait() - } - -fun createPeerAuthenticationUnixDomainSocketPgPool( - vertx: Vertx?, - unixDomainSocketPath: String, database: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): PgPool = - createPeerAuthenticationUnixDomainSocketGenericPgClient( - vertx, unixDomainSocketPath, database, extraPgConnectOptions, poolOptions, PgPool::pool - ) - -fun createPeerAuthenticationUnixDomainSocketPgPoolAndSetRole( - vertx: Vertx?, - host: String, database: String, role: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, poolOptions: PoolOptions = poolOptionsOf() -): PgPool = - createPeerAuthenticationUnixDomainSocketPgPool(vertx, host, database, extraPgConnectOptions, poolOptions) - .connectHandler { - CoroutineScope(Dispatchers.Unconfined).launch { - // TODO: are exceptions handled? - it.executeSetRole(role) - /** @see Pool.connectHandler */ - it.close().coAwait() - } - } - -@Untested -suspend fun createPeerAuthenticationUnixDomainSocketPgConnectionAndSetRole( - vertx: Vertx?, - host: String, database: String, role: String, - extraPgConnectOptions: PgConnectOptions.() -> Unit = {} -): PgConnection = - createPeerAuthenticationUnixDomainSocketGenericPgClient( - vertx, host, database, extraPgConnectOptions, null - ) { vertx, pgConnectOptions, _ -> - PgConnection.connect(vertx, pgConnectOptions).coAwait().apply { - executeSetRole(role) - } - } diff --git a/postgresql/api/exposed-vertx-sql-client-postgresql.api b/postgresql/api/exposed-vertx-sql-client-postgresql.api new file mode 100644 index 0000000..4926d01 --- /dev/null +++ b/postgresql/api/exposed-vertx-sql-client-postgresql.api @@ -0,0 +1,27 @@ +public final class com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClientKt { + public static final fun withPgTransaction (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +} + +public final class com/huanshankeji/exposedvertxsqlclient/postgresql/exposed/ExposedDatabasesKt { + public static final fun exposedDatabaseConnectPostgresql (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Database; + public static synthetic fun exposedDatabaseConnectPostgresql$default (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Database; + public static final fun exposedDatabaseConnectPostgresqlWithParameterConnectionConfig (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/exposed/sql/Database; + public static synthetic fun exposedDatabaseConnectPostgresqlWithParameterConnectionConfig$default (Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig$Socket;Lkotlin/jvm/functions/Function1;Lorg/jetbrains/exposed/sql/DatabaseConfig;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/Database; +} + +public final class com/huanshankeji/exposedvertxsqlclient/postgresql/local/LocalConnectionConfigKt { + public static final field DEFAULT_POSTGRESQL_UNIX_DOMAIN_SOCKET_PATH Ljava/lang/String; + public static final fun defaultPostgresqlLocalConnectionConfig (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lcom/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig; + public static synthetic fun defaultPostgresqlLocalConnectionConfig$default (Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/huanshankeji/exposedvertxsqlclient/local/LocalConnectionConfig; +} + +public final class com/huanshankeji/exposedvertxsqlclient/postgresql/vertx/pgclient/PgClientsKt { + public static final fun createGenericPgClientWithBuilder (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lio/vertx/sqlclient/ClientBuilder;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lio/vertx/sqlclient/SqlClient; + public static final fun createPgClient (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lio/vertx/sqlclient/SqlClient; + public static synthetic fun createPgClient$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lio/vertx/sqlclient/SqlClient; + public static final fun createPgConnection (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun createPgConnection$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun createPgPool (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lio/vertx/sqlclient/Pool; + public static synthetic fun createPgPool$default (Lio/vertx/core/Vertx;Lcom/huanshankeji/exposedvertxsqlclient/ConnectionConfig;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lio/vertx/sqlclient/Pool; +} + diff --git a/postgresql/build.gradle.kts b/postgresql/build.gradle.kts new file mode 100644 index 0000000..cd05fd4 --- /dev/null +++ b/postgresql/build.gradle.kts @@ -0,0 +1,17 @@ +import com.huanshankeji.cpnProject + +plugins { + `lib-conventions` +} + +dependencies { + with(commonDependencies.vertx) { implementation(platformStackDepchain()) } // needed + implementation(cpnProject(project, ":core")) + + // TODO remove the Exposed JDBC dependency and the PostgresSQL dependency when there is no need to to generate SQLs with an Exposed transaction + runtimeOnly(commonDependencies.exposed.module("jdbc")) + runtimeOnly(commonDependencies.postgreSql()) + implementation(commonDependencies.vertx.moduleWithoutVersion("pg-client")) + implementation(commonDependencies.kotlinCommon.core()) // for `Untested` + //implementation(commonDependencies.kotlinCommon.vertx()) // for `PgPoolOptions.setUpConventionally` +} diff --git a/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClient.kt b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/DatabaseClient.kt new file mode 100644 index 0000000..54ea5d2 --- /dev/null +++ b/postgresql/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) diff --git a/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/exposed/ExposedDatabases.kt b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/exposed/ExposedDatabases.kt new file mode 100644 index 0000000..c17199d --- /dev/null +++ b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/exposed/ExposedDatabases.kt @@ -0,0 +1,33 @@ +package com.huanshankeji.exposedvertxsqlclient.postgresql.exposed + +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.exposedvertxsqlclient.exposed.exposedDatabaseConnect +import org.jetbrains.exposed.sql.Database +import org.jetbrains.exposed.sql.DatabaseConfig +import org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManager +import org.jetbrains.exposed.sql.transactions.TransactionManager +import java.sql.Connection + +/** + * @see exposedDatabaseConnect + */ +@ExperimentalEvscApi +fun ConnectionConfig.Socket.exposedDatabaseConnectPostgresql( + setupConnection: (Connection) -> Unit = {}, + databaseConfig: DatabaseConfig? = null, + manager: (Database) -> TransactionManager = { ThreadLocalTransactionManager(it) } +) = + exposedDatabaseConnect( + "postgresql", "org.postgresql.Driver", setupConnection, databaseConfig, manager + ) + +@ExperimentalEvscApi +@JvmName("exposedDatabaseConnectPostgresqlWithParameterConnectionConfig") +fun exposedDatabaseConnectPostgresql( + socketConnectionConfig: ConnectionConfig.Socket, + setupConnection: (Connection) -> Unit = {}, + databaseConfig: DatabaseConfig? = null, + manager: (Database) -> TransactionManager = { ThreadLocalTransactionManager(it) } +) = + socketConnectionConfig.exposedDatabaseConnectPostgresql(setupConnection, databaseConfig, manager) diff --git a/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/local/LocalConnectionConfig.kt b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/local/LocalConnectionConfig.kt new file mode 100644 index 0000000..6187485 --- /dev/null +++ b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/local/LocalConnectionConfig.kt @@ -0,0 +1,16 @@ +package com.huanshankeji.exposedvertxsqlclient.postgresql.local + +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.exposedvertxsqlclient.local.LocalConnectionConfig + +// TODO consider moving to "kotlin-common" + +const val DEFAULT_POSTGRESQL_UNIX_DOMAIN_SOCKET_PATH = "/var/run/postgresql" + +@ExperimentalEvscApi +fun defaultPostgresqlLocalConnectionConfig( + socketConnectionPort: Int? = null, user: String, socketConnectionPassword: String, database: String +) = + LocalConnectionConfig( + socketConnectionPort, DEFAULT_POSTGRESQL_UNIX_DOMAIN_SOCKET_PATH, user, socketConnectionPassword, database + ) diff --git a/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/vertx/pgclient/PgClients.kt b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/vertx/pgclient/PgClients.kt new file mode 100644 index 0000000..700f748 --- /dev/null +++ b/postgresql/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/postgresql/vertx/pgclient/PgClients.kt @@ -0,0 +1,97 @@ +@file:OptIn(ExperimentalEvscApi::class) + +package com.huanshankeji.exposedvertxsqlclient.postgresql.vertx.pgclient + +import com.huanshankeji.Untested +import com.huanshankeji.exposedvertxsqlclient.ConnectionConfig +import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi +import com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient.CoConnectHandler +import com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient.createGenericSqlClient +import com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient.createGenericSqlClientWithBuilder +import com.huanshankeji.exposedvertxsqlclient.vertx.sqlclient.createGenericSqlConnection +import io.vertx.core.Vertx +import io.vertx.pgclient.PgBuilder +import io.vertx.pgclient.PgConnectOptions +import io.vertx.pgclient.PgConnection +import io.vertx.pgclient.impl.PgPoolOptions +import io.vertx.sqlclient.ClientBuilder +import io.vertx.sqlclient.Pool +import io.vertx.sqlclient.SqlClient + +/** + * @see createGenericSqlClient + */ +// made not inline anymore for easier debugging +@ExperimentalEvscApi +fun > createGenericPgClientWithBuilder( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + clientBuilder: ClientBuilderT, + extraPgConnectOptions: PgConnectOptions.() -> Unit, + extraPgPoolOptions: PgPoolOptions.() -> Unit, + connectHandlerExtra: CoConnectHandler +): SqlClientT = + createGenericSqlClientWithBuilder( + vertx, + connectionConfig, + clientBuilder, + PgConnectOptions(), + extraPgConnectOptions, + extraPgPoolOptions, + connectHandlerExtra, + PgPoolOptions() + ) + +fun createPgClient( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, + extraPoolOptions: PgPoolOptions.() -> Unit = {}, + connectHandlerExtra: CoConnectHandler = null, +): SqlClient = + createGenericPgClientWithBuilder( + vertx, + connectionConfig, + PgBuilder.client(), + extraPgConnectOptions, + extraPoolOptions, + connectHandlerExtra + ) + +/** + * @see createGenericSqlClient + */ +fun createPgPool( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, + extraPoolOptions: PgPoolOptions.() -> Unit = {}, + connectHandlerExtra: CoConnectHandler = null, +): Pool = + createGenericPgClientWithBuilder( + vertx, + connectionConfig, + PgBuilder.pool(), + extraPgConnectOptions, + extraPoolOptions, + connectHandlerExtra + ) + +/** + * @see createGenericSqlClient + */ +@Untested +suspend fun createPgConnection( + vertx: Vertx?, + connectionConfig: ConnectionConfig, + extraPgConnectOptions: PgConnectOptions.() -> Unit = {}, + connectHandlerExtra: CoConnectHandler = null +): PgConnection = + createGenericSqlConnection( + vertx, + connectionConfig, + PgConnection::connect, + PgConnectOptions(), + extraPgConnectOptions, + connectHandlerExtra + ) diff --git a/settings.gradle.kts b/settings.gradle.kts index 75fcf49..3b86ea5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,17 @@ rootProject.name = "exposed-vertx-sql-client" -include("lib") -project(":lib").name = rootProject.name + "-postgresql" + +include("core") +include("sql-dsl") +include("sql-dsl-with-mapper") +include("postgresql") +include("integrated") + +fun ProjectDescriptor.setProjectConcatenatedNames(prefix: String) { + name = prefix + name + for (child in children) + child.setProjectConcatenatedNames("$name-") +} +rootProject.setProjectConcatenatedNames("") // for Dokka @Suppress("UnstableApiUsage") diff --git a/sql-dsl-with-mapper/api/exposed-vertx-sql-client-sql-dsl-with-mapper.api b/sql-dsl-with-mapper/api/exposed-vertx-sql-client-sql-dsl-with-mapper.api new file mode 100644 index 0000000..89457fe --- /dev/null +++ b/sql-dsl-with-mapper/api/exposed-vertx-sql-client-sql-dsl-with-mapper.api @@ -0,0 +1,18 @@ +public final class com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapperKt { + public static final fun batchInsertIgnoreWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun batchInsertWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun batchUpdateBuilderSetter (Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;)Lkotlin/jvm/functions/Function3; + public static final fun executeQueryWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Query;Lcom/huanshankeji/exposed/datamapping/DataQueryMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun executeVertxSqlClientRowQueryWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Query;Lcom/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insertIgnoreWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insertWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lcom/huanshankeji/exposed/datamapping/DataQueryMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lcom/huanshankeji/exposed/datamapping/DataQueryMapper;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun updateWithMapper (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun updateWithMapper$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Ljava/lang/Object;Lcom/huanshankeji/exposed/datamapping/DataUpdateMapper;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; +} + +public abstract interface class com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper { + public abstract fun rowToData (Lio/vertx/sqlclient/Row;)Ljava/lang/Object; +} + diff --git a/sql-dsl-with-mapper/build.gradle.kts b/sql-dsl-with-mapper/build.gradle.kts new file mode 100644 index 0000000..92d9e90 --- /dev/null +++ b/sql-dsl-with-mapper/build.gradle.kts @@ -0,0 +1,13 @@ +import com.huanshankeji.cpnProject + +plugins { + `lib-conventions` +} + +dependencies { + with(commonDependencies.vertx) { implementation(platformStackDepchain()) } // needed + implementation(cpnProject(project, ":core")) + implementation(cpnProject(project, ":sql-dsl")) + + implementation("com.huanshankeji:exposed-adt-mapping:${DependencyVersions.exposedAdtMapping}") // for `updateBuilderSetter`, `DataQueryMapper` and `DataUpdateMapper` +} diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt b/sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt similarity index 73% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt rename to sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt index 784ede4..64b4d63 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt +++ b/sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/classpropertymapping/ClassPropertyMapping.kt @@ -6,18 +6,20 @@ import com.huanshankeji.vertx.sqlclient.datamapping.RowDataQueryMapper import io.vertx.sqlclient.Row import kotlin.reflect.KClass +// TODO all definitions are made private because they are not complete yet + /** * @see ClassPropertyColumnMappings */ // since Kotlin 2.0.0: "'Nothing' property type can't be specified with type alias." -typealias ClassPropertyColumnIndexMappings = Unit // TODO +private typealias ClassPropertyColumnIndexMappings = Unit // TODO -typealias VertxSqlClientRowDataQueryMapper = RowDataQueryMapper +private typealias VertxSqlClientRowDataQueryMapper = RowDataQueryMapper /** * @see ReflectionBasedClassPropertyDataMapper */ -class ReflectionBasedClassPropertyIndexVertxSqlClientRowDataQueryMapper( +private class ReflectionBasedClassPropertyIndexVertxSqlClientRowDataQueryMapper( val clazz: KClass, val classPropertyColumnIndexMappings: ClassPropertyColumnIndexMappings ) : RowDataQueryMapper { diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt b/sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt similarity index 66% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt rename to sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt index c6319e5..b45c68e 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt +++ b/sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/mapping/DatabaseClientSqlWithMapper.kt @@ -4,46 +4,51 @@ import com.huanshankeji.exposed.BuildWhere import com.huanshankeji.exposed.datamapping.DataQueryMapper import com.huanshankeji.exposed.datamapping.DataUpdateMapper import com.huanshankeji.exposed.datamapping.updateBuilderSetter -import com.huanshankeji.exposed.deleteIgnoreWhereStatement -import com.huanshankeji.exposed.deleteWhereStatement import com.huanshankeji.exposedvertxsqlclient.DatabaseClient import com.huanshankeji.exposedvertxsqlclient.ExperimentalEvscApi import com.huanshankeji.exposedvertxsqlclient.sql.* import com.huanshankeji.vertx.sqlclient.datamapping.RowDataQueryMapper import io.vertx.sqlclient.RowSet -import org.jetbrains.exposed.sql.* +import org.jetbrains.exposed.sql.ColumnSet +import org.jetbrains.exposed.sql.Query +import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.statements.UpdateBuilder // TODO move to a separate module -// TODO Note that using these DSLs reduces the composability of statements, for example, when moving a query into a subquery. (this statement can be moved into docs some day) @ExperimentalEvscApi -suspend fun DatabaseClient<*>.executeQuery( +suspend fun DatabaseClient<*>.executeQueryWithMapper( query: Query, dataQueryMapper: DataQueryMapper ): RowSet = executeWithMapping(query) { row -> dataQueryMapper.resultRowToData(row.toExposedResultRowWithTransaction(query)) } @ExperimentalEvscApi -suspend fun DatabaseClient<*>.executeVertxSqlClientRowQuery( +suspend fun DatabaseClient<*>.executeVertxSqlClientRowQueryWithMapper( query: Query, rowDataQueryMapper: RowDataQueryMapper ): RowSet = executeWithMapping(query, rowDataQueryMapper::rowToData) @ExperimentalEvscApi -suspend fun DatabaseClient<*>.select( - columnSet: ColumnSet, dataQueryMapper: DataQueryMapper, buildQuery: FieldSet.() -> Query +suspend fun DatabaseClient<*>.selectWithMapper( + columnSet: ColumnSet, dataQueryMapper: DataQueryMapper, buildQuery: Query.() -> Query ) = - executeQuery(columnSet.slice(dataQueryMapper.neededColumns).buildQuery(), dataQueryMapper) + executeQueryWithMapper(columnSet.select(dataQueryMapper.neededColumns).buildQuery(), dataQueryMapper) @ExperimentalEvscApi -suspend fun DatabaseClient<*>.insert( +suspend fun DatabaseClient<*>.selectWithMapper( + columnSet: ColumnSet, dataQueryMapper: DataQueryMapper +) = + selectWithMapper(columnSet, dataQueryMapper) { this } + +@ExperimentalEvscApi +suspend fun DatabaseClient<*>.insertWithMapper( table: Table, data: Data, dataUpdateMapper: DataUpdateMapper ) = insert(table, dataUpdateMapper.updateBuilderSetter(data)) @ExperimentalEvscApi -suspend fun DatabaseClient<*>.insertIgnore( +suspend fun DatabaseClient<*>.insertIgnoreWithMapper( table: Table, data: Data, dataUpdateMapper: DataUpdateMapper ) = insertIgnore(table, dataUpdateMapper.updateBuilderSetter(data)) @@ -56,13 +61,13 @@ fun DataUpdateMapper.batchUpdateBuild // TODO: consider removing the table param by adding it to `DataUpdateMapper` @ExperimentalEvscApi -suspend fun DatabaseClient<*>.batchInsert( +suspend fun DatabaseClient<*>.batchInsertWithMapper( table: Table, data: Iterable, dataUpdateMapper: DataUpdateMapper ) = batchInsert(table, data, dataUpdateMapper.batchUpdateBuilderSetter()) @ExperimentalEvscApi -suspend fun DatabaseClient<*>.batchInsertIgnore( +suspend fun DatabaseClient<*>.batchInsertIgnoreWithMapper( table: Table, data: Iterable, dataUpdateMapper: DataUpdateMapper ) = batchInsertIgnore(table, data, dataUpdateMapper.batchUpdateBuilderSetter()) @@ -72,17 +77,7 @@ suspend fun DatabaseClient<*>.batchInsertIgnore( * In most cases you should specify the fields to update in a more detailed way instead of using this function. */ @ExperimentalEvscApi -suspend fun DatabaseClient<*>.update( +suspend fun DatabaseClient<*>.updateWithMapper( table: Table, where: BuildWhere? = null, limit: Int? = null, data: Data, dataUpdateMapper: DataUpdateMapper ) = update(table, where, limit, dataUpdateMapper.updateBuilderSetter(data)) - -suspend fun DatabaseClient<*>.deleteWhere( - table: T, limit: Int? = null, offset: Long? = null, op: T.(ISqlExpressionBuilder) -> Op -) = - executeUpdate(table.deleteWhereStatement(limit, offset, op)) - -suspend fun DatabaseClient<*>.deleteIgnoreWhere( - table: T, limit: Int? = null, offset: Long? = null, op: T.(ISqlExpressionBuilder) -> Op -) = - executeUpdate(table.deleteIgnoreWhereStatement(limit, offset, op)) diff --git a/lib/src/main/kotlin/com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper.kt b/sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper.kt similarity index 100% rename from lib/src/main/kotlin/com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper.kt rename to sql-dsl-with-mapper/src/main/kotlin/com/huanshankeji/vertx/sqlclient/datamapping/RowDataQueryMapper.kt diff --git a/sql-dsl/api/exposed-vertx-sql-client-sql-dsl.api b/sql-dsl/api/exposed-vertx-sql-client-sql-dsl.api new file mode 100644 index 0000000..b6a5654 --- /dev/null +++ b/sql-dsl/api/exposed-vertx-sql-client-sql-dsl.api @@ -0,0 +1,35 @@ +public final class com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSqlKt { + public static final fun batchInsert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun batchInsertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun batchInsertSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun batchSingleOrNoUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun batchSingleOrNoUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun batchUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun batchUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun deleteIgnoreWhere (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun deleteIgnoreWhere$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun deleteWhere (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun deleteWhere$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Integer;Ljava/lang/Long;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun executeInsertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insert (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insertIgnore (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insertIgnoreSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun insertIgnoreSelect$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun insertIgnoreSingle (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun insertSelect (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun insertSelect$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lorg/jetbrains/exposed/sql/AbstractQuery;Ljava/util/List;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun insertSingle (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun select (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun select (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectBatch (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/FieldSet;Lkotlin/jvm/functions/Function2;Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectColumnSetExpression (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectExpression (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lkotlin/reflect/KClass;Lorg/jetbrains/exposed/sql/Expression;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectSingleColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectSingleColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun selectSingleEntityIdColumn (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/ColumnSet;Lorg/jetbrains/exposed/sql/Column;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun sortDataAndBatchUpdate (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun sortDataAndBatchUpdate$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun update (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun update$default (Lcom/huanshankeji/exposedvertxsqlclient/DatabaseClient;Lorg/jetbrains/exposed/sql/Table;Lkotlin/jvm/functions/Function1;Ljava/lang/Integer;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; +} + diff --git a/sql-dsl/build.gradle.kts b/sql-dsl/build.gradle.kts new file mode 100644 index 0000000..febf3bb --- /dev/null +++ b/sql-dsl/build.gradle.kts @@ -0,0 +1,12 @@ +import com.huanshankeji.cpnProject + +plugins { + `lib-conventions` +} + +dependencies { + with(commonDependencies.vertx) { implementation(platformStackDepchain()) } // needed + implementation(cpnProject(project, ":core")) + + compileOnly(commonDependencies.kotlinCommon.vertx()) // for `sortDataAndExecuteBatch` +} diff --git a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt b/sql-dsl/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt similarity index 81% rename from lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt rename to sql-dsl/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt index 4d0741a..2b47c26 100644 --- a/lib/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt +++ b/sql-dsl/src/main/kotlin/com/huanshankeji/exposedvertxsqlclient/sql/DatabaseClientSql.kt @@ -25,7 +25,6 @@ suspend inline fun DatabaseClient<*>.select( ): RowSet = executeQuery(columnSet.buildQuery(), resultRowMapper) -// TODO adapt to the new SELECT DSL or deprecate suspend inline fun DatabaseClient<*>.select( columnSet: ColumnSet, buildQuery: ColumnSet.() -> Query ): RowSet = @@ -33,50 +32,33 @@ suspend inline fun DatabaseClient<*>.select( select(columnSet, buildQuery, { this }) -// TODO adapt to the new SELECT DSL or deprecate /** * SQL: `SELECT FROM ;`. * Examples: `SELECT COUNT(*) FROM
;`, `SELECT SUM() FROM
;`. */ @ExperimentalEvscApi -suspend fun DatabaseClient<*>.selectTableExpression( - columnSet: ColumnSet, expression: Expression, buildQuery: FieldSet.() -> Query +suspend fun DatabaseClient<*>.selectColumnSetExpression( + columnSet: ColumnSet, expression: Expression, buildQuery: Query.() -> Query ): RowSet = - select(columnSet, { slice(expression).buildQuery() }, { this[expression] }) + select(columnSet, { select(expression).buildQuery() }, { this[expression] }) // This function with `mapper` is not really useful @ExperimentalEvscApi suspend inline fun DatabaseClient<*>.selectSingleColumn( columnSet: ColumnSet, column: Column, - buildQuery: FieldSet.() -> Query, + buildQuery: Query.() -> Query, crossinline mapper: ColumnT.() -> DataT ): RowSet = - select(columnSet, { slice(column).buildQuery() }, { this[column].mapper() }) + select(columnSet, { select(column).buildQuery() }, { this[column].mapper() }) - -@Deprecated("Use `selectSingleColumn`.", ReplaceWith("selectSingleColumn(columnSet, column, buildQuery, mapper)")) -@ExperimentalEvscApi -suspend inline fun DatabaseClient<*>.executeSingleColumnSelectQuery( - columnSet: ColumnSet, column: Column, buildQuery: FieldSet.() -> Query, crossinline mapper: T.() -> R -): RowSet = - selectSingleColumn(columnSet, column, buildQuery, mapper) - -// TODO adapt to the new SELECT DSL or deprecate suspend fun DatabaseClient<*>.selectSingleColumn( - columnSet: ColumnSet, column: Column, buildQuery: FieldSet.() -> Query -): RowSet = - selectTableExpression(columnSet, column, buildQuery) - -@Deprecated("Use `selectSingleColumn`.", ReplaceWith("selectSingleColumn(columnSet, column, buildQuery)")) -suspend fun DatabaseClient<*>.executeSingleColumnSelectQuery( - columnSet: ColumnSet, column: Column, buildQuery: FieldSet.() -> Query + columnSet: ColumnSet, column: Column, buildQuery: Query.() -> Query ): RowSet = - selectSingleColumn(columnSet, column, buildQuery) + selectColumnSetExpression(columnSet, column, buildQuery) -// TODO adapt to the new SELECT DSL or deprecate suspend fun > DatabaseClient<*>.selectSingleEntityIdColumn( - columnSet: ColumnSet, column: Column>, buildQuery: FieldSet.() -> Query + columnSet: ColumnSet, column: Column>, buildQuery: Query.() -> Query ): RowSet = selectSingleColumn(columnSet, column, buildQuery) { value } @@ -87,12 +69,12 @@ suspend fun > DatabaseClient<*>.selectSingleEntityIdColumn( */ // see: https://github.com/JetBrains/Exposed/issues/621 suspend fun DatabaseClient<*>.selectExpression(clazz: KClass, expression: Expression): T? = - executeForVertxSqlClientRowSet(Table.Dual.slice(expression).selectAll()) + executeForVertxSqlClientRowSet(Table.Dual.select(expression)) .single()[clazz.java, 0] suspend inline fun DatabaseClient<*>.selectExpression(expression: Expression): T = @Suppress("UNCHECKED_CAST") - (selectExpression(T::class as KClass, expression as Expression)) as T + selectExpression(T::class as KClass, expression as Expression) as T @ExperimentalEvscApi suspend fun DatabaseClient<*>.insert(table: T, body: T.(InsertStatement) -> Unit) = @@ -152,7 +134,9 @@ suspend fun DatabaseClient<*>.selectBatch( ): Sequence> = executeBatchQuery(fieldSet, data.asSequence().map { fieldSet.buildQuery(it) }.asIterable()) - +/** + * @see DatabaseClient.executeBatchUpdate + */ suspend fun DatabaseClient<*>.batchInsert( table: T, data: Iterable, body: T.(InsertStatement, E) -> Unit ) = @@ -161,6 +145,9 @@ suspend fun DatabaseClient<*>.batchInsert( }.asIterable()) .forEach { dbAssert(it == 1) } +/** + * @see DatabaseClient.executeBatchUpdate + */ suspend fun DatabaseClient<*>.batchInsertIgnore( table: T, data: Iterable, body: T.(InsertStatement, E) -> Unit ) = @@ -172,6 +159,7 @@ suspend fun DatabaseClient<*>.batchInsertIgnore( /** * This function is not conventional and it usages are likely to degrade performance. + * @see DatabaseClient.executeBatchUpdate */ @ExperimentalEvscApi suspend fun DatabaseClient<*>.batchInsertSelect( @@ -179,6 +167,10 @@ suspend fun DatabaseClient<*>.batchInsertSelect( ) = executeBatchUpdate(statements) +/** + * @see DatabaseClient.executeBatchUpdate + * @see sortDataAndBatchUpdate + */ suspend fun DatabaseClient<*>.batchUpdate( table: T, data: Iterable, where: BuildWhere? = null, limit: Int? = null, body: T.(UpdateStatement, E) -> Unit ) = @@ -188,6 +180,7 @@ suspend fun DatabaseClient<*>.batchUpdate( /** * @return a sequence indicating whether each update statement is updated in the batch. + * @see batchUpdate */ suspend fun DatabaseClient<*>.batchSingleOrNoUpdate( table: T, data: Iterable, where: BuildWhere? = null, limit: Int? = null, body: T.(UpdateStatement, E) -> Unit @@ -196,6 +189,7 @@ suspend fun DatabaseClient<*>.batchSingleOrNoUpdate( /** * @see sortDataAndExecuteBatch + * @see batchUpdate */ suspend fun > DatabaseClient<*>.sortDataAndBatchUpdate( table: T, @@ -203,3 +197,14 @@ suspend fun > Databa where: BuildWhere? = null, limit: Int? = null, body: T.(UpdateStatement, E) -> Unit ) = batchUpdate(table, data.sortedBy(selector), where, limit, body) + + +suspend fun DatabaseClient<*>.deleteWhere( + table: T, limit: Int? = null, offset: Long? = null, op: TableAwareWithSqlExpressionBuilderBuildWhere +) = + executeUpdate(table.deleteWhereStatement(limit, offset, op)) + +suspend fun DatabaseClient<*>.deleteIgnoreWhere( + table: T, limit: Int? = null, offset: Long? = null, op: TableAwareWithSqlExpressionBuilderBuildWhere +) = + executeUpdate(table.deleteIgnoreWhereStatement(limit, offset, op))