Skip to content

Commit

Permalink
Merge pull request #57 from momosetkn/feat/custom-jooq-change
Browse files Browse the repository at this point in the history
add custom-jooq-change module
  • Loading branch information
momosetkn authored Oct 5, 2024
2 parents 4c0ddb6 + d947b19 commit 2991f92
Show file tree
Hide file tree
Showing 42 changed files with 797 additions and 43 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,41 @@ changeSet(author = "momose (generated)", id = "1715520327312-40") {
}
```

### Use jOOQ on customChange

`liquibase-kotlin-custom-jooq-change` module can use [jOOQ](https://www.jooq.org/) on customChange

> [!NOTE]
> can use both the `kotlin-script` and `kotlin-compiled`.
add bellow dependencies.

```kotlin
implementation("com.github.momosetkn.liquibase-kotlin:liquibase-kotlin-custom-jooq-change:$liquibaseKotlinVersion")
```

changeSet example
```kotlin
changeSet(author = "momose (generated)", id = "1715520327312-40") {
customJooqChange(
execute = { db ->
val query =
"""
CREATE TABLE created_by_komapper (
id uuid NOT NULL,
name character varying(256)
);
""".trimIndent()
db.execute(query)
},
rollback = { db ->
val query = "DROP TABLE created_by_komapper"
db.execute(query)
},
)
}
```

## Prerequisite

- JDK 17 or later
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ val libraryProjects =
"client",
// custom-change
"custom-komapper-jdbc-change",
"custom-jooq-change",
"custom-change-core",
)
}
configure(libraryProjects) {
Expand Down
21 changes: 21 additions & 0 deletions custom-change-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
val liquibaseVersion = rootProject.properties["liquibaseVersion"] as String
val kotestVersion = rootProject.properties["kotestVersion"] as String
val liquibaseKotlinVersion = rootProject.properties["liquibaseKotlinVersion"] as String
val kotlinVersion = rootProject.properties["kotlinVersion"] as String

dependencies {
implementation(project(":dsl"))
// liquibase
implementation("org.liquibase:liquibase-core:$liquibaseVersion")
// reflection
api("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")

// test
testImplementation("io.kotest:kotest-framework-engine-jvm:$kotestVersion")
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
}

tasks.test {
useJUnitPlatform()
systemProperty("kotest.framework.classpath.scanning.config.disable", "true")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package momosetkn.liquibase.kotlin.change.custom.komapper

import liquibase.change.custom.CustomChange
import liquibase.change.custom.CustomChangeWrapper
import liquibase.change.custom.setCustomChange
import momosetkn.liquibase.kotlin.dsl.ChangeSetDsl

fun ChangeSetDsl.addCustomChange(change: CustomChange) {
val customChangeWrapper = this.changeSetSupport.createChange("customChange") as CustomChangeWrapper
customChangeWrapper.setCustomChange(change)
changeSetSupport.addChange(customChangeWrapper)
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package momosetkn.liquibase.kotlin.change
package momosetkn.liquibase.kotlin.change.custom.komapper

import momosetkn.sql.DatasourceProxy
import momosetkn.sql.NotCloseConnectionProxy
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible

internal fun liquibase.database.Database.toKomapperJdbcDatabase(): org.komapper.jdbc.JdbcDatabase {
val datasource = this.toJavaxSqlDataSource()
val database = LiquibaseKomapperJdbcConfig.provideJdbcDatabase(datasource, this.shortName)
return database
}

private fun liquibase.database.Database.toJavaxSqlDataSource(): DatasourceProxy {
fun liquibase.database.Database.toJavaxSqlDataSource(): DatasourceProxy {
val liquibaseJdbcConnection = this.connection as liquibase.database.jvm.JdbcConnection
val con = connectionProperty.get(liquibaseJdbcConnection) as java.sql.Connection
return DatasourceProxy(NotCloseConnectionProxy(con))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.util.concurrent.Executor
/**
* Not close connection.
* Closed by liquibase.
* therefore, not close in custom-komappaer-jdbc-change.
* therefore, not close in custom-change.
*/
@Suppress("TooManyFunctions")
class NotCloseConnectionProxy(
Expand Down
26 changes: 26 additions & 0 deletions custom-jooq-change/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
val liquibaseVersion = rootProject.properties["liquibaseVersion"] as String
val kotestVersion = rootProject.properties["kotestVersion"] as String
val liquibaseKotlinVersion = rootProject.properties["liquibaseKotlinVersion"] as String
val kotlinVersion = rootProject.properties["kotlinVersion"] as String
val jooqVersion = rootProject.properties["jooqVersion"] as String

dependencies {
implementation(project(":dsl"))
implementation(project(":script-parser"))
api(project(":custom-change-core"))
// liquibase
implementation("org.liquibase:liquibase-core:$liquibaseVersion")
// jooq
implementation("org.jooq:jooq:$jooqVersion")
// reflection
api("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")

// test
testImplementation("io.kotest:kotest-framework-engine-jvm:$kotestVersion")
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
}

tasks.test {
useJUnitPlatform()
systemProperty("kotest.framework.classpath.scanning.config.disable", "true")
}
7 changes: 7 additions & 0 deletions custom-jooq-change/detekt-baseline.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" ?>
<SmellBaseline>
<ManuallySuppressedIssues></ManuallySuppressedIssues>
<CurrentIssues>
<ID>ForbiddenComment:RollbackTaskCustomJooqChange.kt$RollbackTaskCustomJooqChange$// FIXME: CustomTaskRollback has a bug that causes it to be rolled back twice, but there is a workaround.</ID>
</CurrentIssues>
</SmellBaseline>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import momosetkn.liquibase.kotlin.parser.KotlinScriptParserImports

class CustomJooqChangeParserImports : KotlinScriptParserImports {
override fun imports() = listOf(
"momosetkn.liquibase.kotlin.change.custom.jooq.customJooqChange",
"org.jooq.core.dsl.QueryDsl",
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import liquibase.exception.ValidationErrors
import momosetkn.liquibase.kotlin.change.custom.komapper.addCustomChange
import momosetkn.liquibase.kotlin.dsl.ChangeSetDsl

fun ChangeSetDsl.customJooqChange(
confirmationMessage: String = "Executed CustomJooqChange.",
rollback: ((org.jooq.DSLContext) -> Unit)? = null,
validate: (org.jooq.DSLContext) -> ValidationErrors = { ValidationErrors() },
execute: (org.jooq.DSLContext) -> Unit,
) {
val change = if (rollback != null) {
val define = CustomRollbackableTaskChangeDefineImpl(
execute,
validate,
rollback,
confirmationMessage,
)
RollbackTaskCustomJooqChange(define)
} else {
val define = CustomTaskChangeDefineImpl(
execute,
validate,
confirmationMessage,
)
ForwardOnlyTaskCustomJooqChange(define)
}
addCustomChange(change)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import liquibase.exception.ValidationErrors

sealed interface CustomTaskChangeDefine

data class CustomTaskChangeDefineImpl(
val executeBlock: (org.jooq.DSLContext) -> Unit,
val validateBlock: (org.jooq.DSLContext) -> ValidationErrors,
val confirmationMessage: String,
) : CustomTaskChangeDefine

data class CustomRollbackableTaskChangeDefineImpl(
val executeBlock: (org.jooq.DSLContext) -> Unit,
val validateBlock: (org.jooq.DSLContext) -> ValidationErrors,
val rollbackBlock: (org.jooq.DSLContext) -> Unit,
val confirmationMessage: String,
) : CustomTaskChangeDefine
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import liquibase.change.custom.CustomChange
import liquibase.change.custom.CustomTaskChange
import liquibase.database.Database
import liquibase.exception.ValidationErrors
import liquibase.resource.ResourceAccessor

class ForwardOnlyTaskCustomJooqChange(
private val define: CustomTaskChangeDefineImpl,
) : CustomChange, CustomTaskChange {
private var resourceAccessor: ResourceAccessor? = null
override fun getConfirmationMessage(): String {
return define.confirmationMessage
}

override fun setUp() = Unit

override fun setFileOpener(resourceAccessor: ResourceAccessor) {
this.resourceAccessor = resourceAccessor
}

override fun validate(database: Database): ValidationErrors {
return define.validateBlock(database.toJooqDSLContext())
}

override fun execute(database: Database) {
define.executeBlock(database.toJooqDSLContext())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import momosetkn.liquibase.kotlin.change.custom.komapper.toJavaxSqlDataSource

internal fun liquibase.database.Database.toJooqDSLContext(): org.jooq.DSLContext {
val datasource = this.toJavaxSqlDataSource()
val database = LiquibaseJooqConfig.provideDSLContext(datasource, this.shortName)
return database
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import org.jooq.SQLDialect
import org.jooq.impl.DefaultDSLContext

object LiquibaseJooqConfig {
private val dialectMap =
SQLDialect.entries.associateBy { it.name.lowercase() } + mapOf(
"postgresql" to SQLDialect.POSTGRES,
)

var provideDSLContext: (
javaxSqlDataSource: javax.sql.DataSource,
liquibaseDatabaseShortName: String
) -> org.jooq.DSLContext = ::defaultProvideDSLContext

fun defaultProvideDSLContext(
javaxSqlDataSource: javax.sql.DataSource,
liquibaseDatabaseShortName: String
): org.jooq.DSLContext {
return DefaultDSLContext(javaxSqlDataSource, getDialect(liquibaseDatabaseShortName))
}

private fun getDialect(liquibaseDatabaseShortName: String): SQLDialect {
return dialectMap[liquibaseDatabaseShortName] ?: SQLDialect.DEFAULT
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package momosetkn.liquibase.kotlin.change.custom.jooq

import liquibase.change.custom.CustomChange
import liquibase.change.custom.CustomTaskChange
import liquibase.change.custom.CustomTaskRollback
import liquibase.database.Database
import liquibase.exception.ValidationErrors
import liquibase.resource.ResourceAccessor

class RollbackTaskCustomJooqChange(
private val define: CustomRollbackableTaskChangeDefineImpl,
) : CustomChange, CustomTaskChange, CustomTaskRollback {
private var alreadyRollbackFlg = false
private var resourceAccessor: ResourceAccessor? = null
override fun getConfirmationMessage(): String {
return define.confirmationMessage
}

override fun setUp() = Unit

override fun setFileOpener(resourceAccessor: ResourceAccessor) {
this.resourceAccessor = resourceAccessor
}

override fun validate(database: Database): ValidationErrors {
return define.validateBlock(database.toJooqDSLContext())
}

override fun execute(database: Database) {
define.executeBlock(database.toJooqDSLContext())
}

override fun rollback(database: Database) {
// FIXME: CustomTaskRollback has a bug that causes it to be rolled back twice, but there is a workaround.
// bugfix: https://github.com/liquibase/liquibase/pull/6266
if (!alreadyRollbackFlg) {
define.rollbackBlock(database.toJooqDSLContext())
alreadyRollbackFlg = true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
momosetkn.liquibase.kotlin.change.custom.jooq.CustomJooqChangeParserImports
Loading

0 comments on commit 2991f92

Please sign in to comment.