Skip to content

Commit

Permalink
chore: Add migration module and move generateMigrationScript functi…
Browse files Browse the repository at this point in the history
…on to it
  • Loading branch information
joc-a committed Jun 20, 2024
1 parent c514f9f commit a1bce20
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 44 deletions.
2 changes: 0 additions & 2 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -2026,8 +2026,6 @@ public final class org/jetbrains/exposed/sql/SchemaUtils {
public static synthetic fun dropSchema$default (Lorg/jetbrains/exposed/sql/SchemaUtils;[Lorg/jetbrains/exposed/sql/Schema;ZZILjava/lang/Object;)V
public final fun dropSequence ([Lorg/jetbrains/exposed/sql/Sequence;Z)V
public static synthetic fun dropSequence$default (Lorg/jetbrains/exposed/sql/SchemaUtils;[Lorg/jetbrains/exposed/sql/Sequence;ZILjava/lang/Object;)V
public final fun generateMigrationScript ([Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;Z)Ljava/io/File;
public static synthetic fun generateMigrationScript$default (Lorg/jetbrains/exposed/sql/SchemaUtils;[Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Ljava/io/File;
public final fun listDatabases ()Ljava/util/List;
public final fun listTables ()Ljava/util/List;
public final fun setSchema (Lorg/jetbrains/exposed/sql/Schema;Z)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import org.jetbrains.exposed.exceptions.ExposedSQLException
import org.jetbrains.exposed.sql.SqlExpressionBuilder.asLiteral
import org.jetbrains.exposed.sql.transactions.TransactionManager
import org.jetbrains.exposed.sql.vendors.*
import java.io.File
import java.math.BigDecimal

/** Utility functions that assist with creating, altering, and dropping database schema objects. */
Expand Down Expand Up @@ -849,44 +848,6 @@ object SchemaUtils {
return toDrop.toList()
}

/**
* @param tables The tables whose changes will be used to generate the migration script.
* @param scriptName The name to be used for the generated migration script.
* @param scriptDirectory The directory (path from repository root) in which to create the migration script.
* @param withLogs By default, a description for each intermediate step, as well as its execution time, is logged at
* the INFO level. This can be disabled by setting [withLogs] to `false`.
*
* @return The generated migration script.
*
* @throws IllegalArgumentException if no argument is passed for the [tables] parameter.
*
* This function simply generates the migration script without applying the migration. Its purpose is to show what
* the migration script will look like before applying the migration.
* If a migration script with the same name already exists, its content will be overwritten.
*/
@ExperimentalDatabaseMigrationApi
fun generateMigrationScript(vararg tables: Table, scriptDirectory: String, scriptName: String, withLogs: Boolean = true): File {
require(tables.isNotEmpty()) { "Tables argument must not be empty" }

val allStatements = statementsRequiredForDatabaseMigration(*tables, withLogs = withLogs)

val migrationScript = File("$scriptDirectory/$scriptName.sql")
migrationScript.createNewFile()

// Clear existing content
migrationScript.writeText("")

// Append statements
allStatements.forEach { statement ->
// Add semicolon only if it's not already there
val conditionalSemicolon = if (statement.last() == ';') "" else ";"

migrationScript.appendText("$statement$conditionalSemicolon\n")
}

return migrationScript
}

/**
* Returns the SQL statements that need to be executed to make the existing database schema compatible with
* the table objects defined using Exposed. Unlike [statementsRequiredToActualizeScheme], DROP/DELETE statements are
Expand Down
6 changes: 6 additions & 0 deletions exposed-migration/api/exposed-migration.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public final class MigrationUtils {
public static final field INSTANCE LMigrationUtils;
public final fun generateMigrationScript ([Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;Z)Ljava/io/File;
public static synthetic fun generateMigrationScript$default (LMigrationUtils;[Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Ljava/io/File;
}

22 changes: 22 additions & 0 deletions exposed-migration/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id("java")
}

repositories {
mavenCentral()
}

dependencies {
api(project(":exposed-core"))

testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
useJUnitPlatform()
}

kotlin {
jvmToolchain(8)
}
44 changes: 44 additions & 0 deletions exposed-migration/src/main/kotlin/MigrationUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import org.jetbrains.exposed.sql.ExperimentalDatabaseMigrationApi
import org.jetbrains.exposed.sql.SchemaUtils.statementsRequiredForDatabaseMigration
import org.jetbrains.exposed.sql.Table
import java.io.File

object MigrationUtils {
/**
* This function simply generates the migration script without applying the migration. Its purpose is to show what
* the migration script will look like before applying the migration. If a migration script with the same name
* already exists, its content will be overwritten.
*
* @param tables The tables whose changes will be used to generate the migration script.
* @param scriptName The name to be used for the generated migration script.
* @param scriptDirectory The directory (path from repository root) in which to create the migration script.
* @param withLogs By default, a description for each intermediate step, as well as its execution time, is logged at
* the INFO level. This can be disabled by setting [withLogs] to `false`.
*
* @return The generated migration script.
*
* @throws IllegalArgumentException if no argument is passed for the [tables] parameter.
*/
@ExperimentalDatabaseMigrationApi
fun generateMigrationScript(vararg tables: Table, scriptDirectory: String, scriptName: String, withLogs: Boolean = true): File {
require(tables.isNotEmpty()) { "Tables argument must not be empty" }

val allStatements = statementsRequiredForDatabaseMigration(*tables, withLogs = withLogs)

val migrationScript = File("$scriptDirectory/$scriptName.sql")
migrationScript.createNewFile()

// Clear existing content
migrationScript.writeText("")

// Append statements
allStatements.forEach { statement ->
// Add semicolon only if it's not already there
val conditionalSemicolon = if (statement.last() == ';') "" else ";"

migrationScript.appendText("$statement$conditionalSemicolon\n")
}

return migrationScript
}
}
1 change: 1 addition & 0 deletions exposed-tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dependencies {
implementation(project(":exposed-jdbc"))
implementation(project(":exposed-dao"))
implementation(project(":exposed-kotlin-datetime"))
implementation(project(":exposed-migration"))

implementation(libs.slf4j)
implementation(libs.log4j.slf4j.impl)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
try {
SchemaUtils.create(noPKTable)

val script = SchemaUtils.generateMigrationScript(singlePKTable, scriptDirectory = scriptDirectory, scriptName = scriptName)
val script = MigrationUtils.generateMigrationScript(singlePKTable, scriptDirectory = scriptDirectory, scriptName = scriptName)
assertTrue(script.exists())
assertEquals("src/test/resources/$scriptName.sql", script.path)

Expand Down Expand Up @@ -86,7 +86,7 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
}

// Generate script with the same name of initial script
val newScript = SchemaUtils.generateMigrationScript(singlePKTable, scriptDirectory = directory, scriptName = name)
val newScript = MigrationUtils.generateMigrationScript(singlePKTable, scriptDirectory = directory, scriptName = name)

val expectedStatements: List<String> = SchemaUtils.statementsRequiredForDatabaseMigration(singlePKTable)
assertEquals(1, expectedStatements.size)
Expand All @@ -106,7 +106,7 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
fun testNoTablesPassedWhenGeneratingMigrationScript() {
withDb {
expectException<IllegalArgumentException> {
SchemaUtils.generateMigrationScript(scriptDirectory = "src/test/resources", scriptName = "V2__Test")
MigrationUtils.generateMigrationScript(scriptDirectory = "src/test/resources", scriptName = "V2__Test")
}
}
}
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include("exposed-bom")
include("exposed-kotlin-datetime")
include("exposed-crypt")
include("exposed-json")
include("exposed-migration")

pluginManagement {
repositories {
Expand Down

0 comments on commit a1bce20

Please sign in to comment.