Skip to content

Commit

Permalink
GH-88 Support dialect-specific transactions and release 1.0.0-alpha.68 (
Browse files Browse the repository at this point in the history
Resolve #88)
  • Loading branch information
dzikoysk committed Jan 12, 2025
1 parent 4cd979b commit 71801ff
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ plugins {
}

dependencies {
val sqiffy = "1.0.0-alpha.67"
val sqiffy = "1.0.0-alpha.68"
ksp("com.dzikoysk.sqiffy:sqiffy-symbol-processor:$sqiffy") // annotation processor
implementation("com.dzikoysk.sqiffy:sqiffy:$sqiffy") // core library & implementation
}
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ allprojects {
apply(plugin = "signing")

group = "com.dzikoysk.sqiffy"
version = "1.0.0-alpha.67"
version = "1.0.0-alpha.68"

java {
sourceCompatibility = JavaVersion.VERSION_11
Expand Down
2 changes: 1 addition & 1 deletion sqiffy-docs/installation/gradle.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
}

dependencies {
val sqiffy = "1.0.0-alpha.67"
val sqiffy = "1.0.0-alpha.68"
ksp("com.dzikoysk.sqiffy:sqiffy-symbol-processor:$sqiffy")
implementation("com.dzikoysk.sqiffy:sqiffy:$sqiffy")
}
Expand Down
91 changes: 47 additions & 44 deletions sqiffy-test/src/test/kotlin/com/dzikoysk/sqiffy/e2e/DslE2ETest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.dzikoysk.sqiffy.definition.ChangelogProvider
import com.dzikoysk.sqiffy.definition.ChangelogProvider.LIQUIBASE
import com.dzikoysk.sqiffy.definition.ChangelogProvider.SQIFFY
import com.dzikoysk.sqiffy.dialect.postgres.PostgresDatabase
import com.dzikoysk.sqiffy.dialect.postgres.invoke
import com.dzikoysk.sqiffy.domain.TestDefault
import com.dzikoysk.sqiffy.domain.UnidentifiedUser
import com.dzikoysk.sqiffy.domain.toUser
Expand Down Expand Up @@ -221,50 +222,52 @@ class EmbeddedPostgresUpsertDslE2ETest : SqiffyE2ETestSpecification() {
val role: Role
)

val firstResult =
postgresDatabase
.upsert(UserTable)
.insert {
it[UserTable.id] = 1
it[UserTable.name] = "1"
it[UserTable.displayName] = "1"
it[UserTable.uuid] = UUID.randomUUID()
it[UserTable.wallet] = 100f
it[UserTable.role] = MODERATOR
}
.update {
it[UserTable.name] = "2"
it[UserTable.displayName] = "2"
}
.execute { View(it[UserTable.id], it[UserTable.name], it[UserTable.role]) }
.first()

assertThat(firstResult.id).isEqualTo(1) // conflict
assertThat(firstResult.name).isEqualTo("1") // updated field
assertThat(firstResult.role).isEqualTo(MODERATOR) // non updated field

val secondResult =
postgresDatabase
.upsert(UserTable) { listOf(it.id) }
.insert {
it[UserTable.id] = 1
it[UserTable.name] = "1"
it[UserTable.displayName] = "1"
it[UserTable.uuid] = UUID.randomUUID()
it[UserTable.wallet] = 100f
it[UserTable.role] = MODERATOR
}
.update {
it[UserTable.name] = "2"
it[UserTable.displayName] = "2"
}
.execute { View(it[UserTable.id], it[UserTable.name], it[UserTable.role]) }
.first()

assertThat(secondResult.id).isEqualTo(1) // conflict
assertThat(secondResult.name).isEqualTo("2") // updated field
assertThat(secondResult.role).isEqualTo(MODERATOR) // non updated field
}
database.transaction { transaction ->
val firstResult =
postgresDatabase(transaction)
.upsert(UserTable)
.insert {
it[UserTable.id] = 1
it[UserTable.name] = "1"
it[UserTable.displayName] = "1"
it[UserTable.uuid] = UUID.randomUUID()
it[UserTable.wallet] = 100f
it[UserTable.role] = MODERATOR
}
.update {
it[UserTable.name] = "2"
it[UserTable.displayName] = "2"
}
.execute { View(it[UserTable.id], it[UserTable.name], it[UserTable.role]) }
.first()

assertThat(firstResult.id).isEqualTo(1) // conflict
assertThat(firstResult.name).isEqualTo("1") // updated field
assertThat(firstResult.role).isEqualTo(MODERATOR) // non updated field

val secondResult =
postgresDatabase
.upsert(UserTable) { listOf(it.id) }
.insert {
it[UserTable.id] = 1
it[UserTable.name] = "1"
it[UserTable.displayName] = "1"
it[UserTable.uuid] = UUID.randomUUID()
it[UserTable.wallet] = 100f
it[UserTable.role] = MODERATOR
}
.update {
it[UserTable.name] = "2"
it[UserTable.displayName] = "2"
}
.execute { View(it[UserTable.id], it[UserTable.name], it[UserTable.role]) }
.first()

assertThat(secondResult.id).isEqualTo(1) // conflict
assertThat(secondResult.name).isEqualTo("2") // updated field
assertThat(secondResult.role).isEqualTo(MODERATOR) // non updated field
}
}
}


Expand Down
6 changes: 6 additions & 0 deletions sqiffy/src/main/kotlin/com/dzikoysk/sqiffy/SqiffyDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ abstract class SqiffyDatabase(state: SqiffyDatabaseConfig) : DslHandle, Transact
block.invoke(JdbiTransaction(handle))
}

operator fun invoke(transaction: Transaction?): DslHandle =
when (transaction) {
is JdbiTransaction -> JdbiDslHandle(this, transaction.handle)
else -> this
}

fun with(transaction: Transaction?): DslHandle =
when (transaction) {
is JdbiTransaction -> JdbiDslHandle(this, transaction.handle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,29 @@ import com.dzikoysk.sqiffy.changelog.generator.dialects.PostgreSqlSchemeGenerato
import com.dzikoysk.sqiffy.definition.NamingStrategy.RAW
import com.dzikoysk.sqiffy.dialect.Dialect.POSTGRESQL
import com.dzikoysk.sqiffy.dialect.createGenericJdbi
import com.dzikoysk.sqiffy.dsl.Column
import com.dzikoysk.sqiffy.dsl.Table
import com.dzikoysk.sqiffy.dsl.TableWithAutogeneratedKey
import com.dzikoysk.sqiffy.dsl.*
import com.dzikoysk.sqiffy.dsl.generator.dialects.PostgreSqlQueryGenerator
import com.dzikoysk.sqiffy.transaction.JdbiTransaction
import com.dzikoysk.sqiffy.transaction.NoTransaction
import com.dzikoysk.sqiffy.transaction.Transaction
import com.zaxxer.hikari.HikariDataSource
import org.jdbi.v3.core.Handle
import org.jdbi.v3.postgres.PostgresPlugin

import kotlin.internal.LowPriorityInOverloadResolution

class PostgresDatabase(state: SqiffyDatabaseConfig) : SqiffyDatabase(state) {
interface PostgresDslHandle : DslHandle {

companion object {
fun createPostgresDatabase(
logger: SqiffyLogger = StdoutSqiffyLogger(),
dataSource: HikariDataSource
): PostgresDatabase {
return PostgresDatabase(
state = SqiffyDatabaseConfig(
logger = logger,
dataSource = dataSource,
localJdbi = createGenericJdbi(dataSource).also {
it.installPlugin(PostgresPlugin())
},
dialect = POSTGRESQL,
sqlQueryGenerator = PostgreSqlQueryGenerator,
changelogBuilder = ChangelogBuilder(PostgreSqlSchemeGenerator, RAW)
)
)
}
}
fun <T : Table> upsert(
table: T,
conflictingColumns: (T) -> Collection<Column<*>>,
): UpsertStatement =
upsert(
table = table,
insertValues = null,
updateValues = null,
conflictingColumns = conflictingColumns
)

@LowPriorityInOverloadResolution
fun upsert(
Expand All @@ -56,17 +49,6 @@ class PostgresDatabase(state: SqiffyDatabaseConfig) : SqiffyDatabase(state) {
updateValuesSupplier = updateValues
)

fun <T : Table> upsert(
table: T,
conflictingColumns: (T) -> Collection<Column<*>>,
): UpsertStatement =
upsert(
table = table,
insertValues = null,
updateValues = null,
conflictingColumns = conflictingColumns
)

@LowPriorityInOverloadResolution
fun <T : Table> upsert(
table: T,
Expand All @@ -83,4 +65,43 @@ class PostgresDatabase(state: SqiffyDatabaseConfig) : SqiffyDatabase(state) {
conflictingColumns = conflictingColumns(table),
)

}
}

class PostgresDatabase(state: SqiffyDatabaseConfig) : PostgresDslHandle, SqiffyDatabase(state) {

companion object {
fun createPostgresDatabase(
logger: SqiffyLogger = StdoutSqiffyLogger(),
dataSource: HikariDataSource
): PostgresDatabase {
return PostgresDatabase(
state = SqiffyDatabaseConfig(
logger = logger,
dataSource = dataSource,
localJdbi = createGenericJdbi(dataSource).also {
it.installPlugin(PostgresPlugin())
},
dialect = POSTGRESQL,
sqlQueryGenerator = PostgreSqlQueryGenerator,
changelogBuilder = ChangelogBuilder(PostgreSqlSchemeGenerator, RAW)
)
)
}
}

operator fun invoke(transaction: Transaction): PostgresDslHandle =
transaction.invoke(this)

}

class PostgresJdbiDslHandle(
database: PostgresDatabase,
handle: Handle
) : PostgresDslHandle, JdbiDslHandle<PostgresDatabase>(database, handle)

@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
operator fun Transaction.invoke(database: PostgresDatabase): PostgresDslHandle =
when (this) {
is JdbiTransaction -> PostgresJdbiDslHandle(database, handle)
NoTransaction -> database
}
9 changes: 6 additions & 3 deletions sqiffy/src/main/kotlin/com/dzikoysk/sqiffy/dsl/DslHandle.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ interface DslHandle {

}

class JdbiDslHandle(private val database: SqiffyDatabase, private val handle: Handle) : DslHandle, HandleAccessor {
open class JdbiDslHandle<DATABASE : SqiffyDatabase>(
protected val internalDatabase: DATABASE,
protected val handle: Handle,
) : DslHandle, HandleAccessor {

override fun <R> inHandle(body: (Handle) -> R): R =
body.invoke(handle)

override fun getHandleAccessor(): HandleAccessor =
this

override fun getDatabase(): SqiffyDatabase =
database
override fun getDatabase(): DATABASE =
internalDatabase

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
@file:Suppress("internal", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")

package com.dzikoysk.sqiffy.transaction

import com.dzikoysk.sqiffy.SqiffyDatabase
import com.dzikoysk.sqiffy.dsl.DslHandle
import com.dzikoysk.sqiffy.dsl.JdbiDslHandle
import org.jdbi.v3.core.Handle
import kotlin.internal.LowPriorityInOverloadResolution

sealed interface Transaction {
@LowPriorityInOverloadResolution
operator fun invoke(database: SqiffyDatabase): DslHandle
}

Expand Down

0 comments on commit 71801ff

Please sign in to comment.