Skip to content

Commit

Permalink
Merge branch 'main' into release
Browse files Browse the repository at this point in the history
v0.4.0 release
  • Loading branch information
ShreckYe committed Oct 19, 2024
2 parents 2a7066d + 96af579 commit a3b92c5
Show file tree
Hide file tree
Showing 18 changed files with 423 additions and 56 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.gradle
.kotlin
build
.idea
118 changes: 113 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

## Note

This project currently serves our own use and there are temporarily no guides or docs. 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.

Only PostgreSQL with [Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg-client/java/) is currently supported.

## Maven coordinate
Expand All @@ -16,7 +14,117 @@ Only PostgreSQL with [Reactive PostgreSQL Client](https://vertx.io/docs/vertx-pg
"com.huanshankeji:exposed-vertx-sql-client-postgresql:$version"
```

## About the code
## 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 [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.

### Create a `DatabaseClient`

```kotlin
val socketConnectionConfig =
ConnectionConfig.Socket("localhost", user = "user", password = "password", database = "database")
val exposedDatabase = exposedDatabaseConnectPostgreSql(socketConnectionConfig)
val databaseClient = createPgPoolDatabaseClient(
vertx, socketConnectionConfig, exposedDatabase = exposedDatabase
)
```

### Example table definitions

```kotlin
object Examples : IntIdTable("examples") {
val name = varchar("name", 64)
}

val tables = arrayOf(Examples)
```

### Use `exposedTransaction` to execute original blocking Exposed code

For example, to create tables:

```kotlin
withContext(Dispatchers.IO) {
databaseClient.exposedTransaction {
SchemaUtils.create(*tables)
}
}
```

### 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.

```kotlin
// The Exposed `Table` extension functions `insert`, `update`, and `delete` execute eagerly so `insertStatement`, `updateStatement`, `deleteStatement` have to be used.

val insertRowCount = databaseClient.executeUpdate(Examples.insertStatement { it[name] = "A" })
assert(insertRowCount == 1)
// `executeSingleUpdate` function requires that there is only 1 row updated and returns `Unit`.
databaseClient.executeSingleUpdate(Examples.insertStatement { it[name] = "B" })
// `executeSingleOrNoUpdate` requires that there is 0 or 1 row updated and returns `Boolean`.
val isInserted = databaseClient.executeSingleOrNoUpdate(Examples.insertIgnoreStatement { it[name] = "B" })
assert(isInserted)

val updateRowCount =
databaseClient.executeUpdate(Examples.updateStatement({ Examples.id eq 1 }) { it[name] = "AA" })
assert(updateRowCount == 1)

// The Exposed `Table` extension function `select` doesn't execute eagerly so it can be used directly.
val exampleName = databaseClient.executeQuery(Examples.select(Examples.name).where(Examples.id eq 1))
.single()[Examples.name]

databaseClient.executeSingleUpdate(Examples.deleteWhereStatement { Examples.id eq 1 }) // The function `deleteWhereStatement` still depends on the old DSL and will be updated.
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:

```kotlin
databaseClient.insert(Examples) { it[name] = "A" }
val isInserted = databaseClient.insertIgnore(Examples) { it[name] = "B" }

val updateRowCount = databaseClient.update(Examples, { Examples.id eq 1 }) { it[name] = "AA" }

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()

val deleteRowCount1 = databaseClient.deleteWhere(Examples) { id eq 1 }
assert(deleteRowCount1 == 1)
val deleteRowCount2 = databaseClient.deleteIgnoreWhere(Examples) { id eq 2 }
assert(deleteRowCount2 == 1)
```

#### APIs using [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).

```kotlin
val directorId = 1
val director = Director(directorId, "George Lucas")
databaseClient.insert(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)

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

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.
}
```

### About the code

Also see https://github.com/huanshankeji/kotlin-common/tree/main/exposed for some dependency code which serves this
library.
Also see <https://github.com/huanshankeji/kotlin-common/tree/main/exposed> for some dependency code which serves this library.
7 changes: 4 additions & 3 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ repositories {
}

dependencies {
implementation(kotlin("gradle-plugin", "1.9.23"))
implementation("com.huanshankeji:common-gradle-dependencies:0.7.1-20240314")
implementation("com.huanshankeji.team:gradle-plugins:0.5.1")
// 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
}
7 changes: 4 additions & 3 deletions buildSrc/src/main/kotlin/VersionsAndDependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import com.huanshankeji.CommonDependencies
import com.huanshankeji.CommonGradleClasspathDependencies
import com.huanshankeji.CommonVersions

val projectVersion = "0.3.0"
val projectVersion = "0.4.0"

val commonVersions = CommonVersions()
// don't use a snapshot version in a main branch
val commonVersions = CommonVersions(kotlinCommon = "0.5.1")
val commonDependencies = CommonDependencies(commonVersions)
val commonGradleClasspathDependencies = CommonGradleClasspathDependencies(commonVersions)

object DependencyVersions {
val exposedAdtMapping = "0.1.0"
val exposedAdtMapping = "0.2.0"
}
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
7 changes: 5 additions & 2 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down Expand Up @@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
2 changes: 2 additions & 0 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.huanshankeji.exposedvertxsqlclient

sealed interface ConnectionConfig {
val userAndRole: String
val database: String

class Socket(
val host: String,
val port: Int? = null, // `null` for the default port
val user: String,
val password: String,
override val database: String
) : ConnectionConfig {
override val userAndRole: String get() = user
}

class UnixDomainSocketWithPeerAuthentication(
val path: String,
val role: String,
override val database: String
) : ConnectionConfig {
override val userAndRole: String get() = role
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.huanshankeji.exposedvertxsqlclient

enum class ConnectionType {
Socket, UnixDomainSocketWithPeerAuthentication
}
Loading

0 comments on commit a3b92c5

Please sign in to comment.