All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vladsch.kotlin.jdbc.MigrationSession.kt Maven / Gradle / Ivy

Go to download

A thin library that exposes JDBC API with the convenience of Kotlin and gets out of the way when not needed.

The newest version!
package com.vladsch.kotlin.jdbc

import org.intellij.lang.annotations.Language
import java.time.LocalDateTime

class MigrationSession(val batchId: Int, val version: String, val migrations: Migrations) {
    data class Migration(
        val migration_id: Int,
        val version: String,
        val batch_id: Int,
        val applied_at: LocalDateTime,
        val migration_type: Int?,
        val script_name: String,
        val script_sql: String,
        val rolled_back_id: Int?,
        val last_problem: String?
    ) {

        companion object {
            @JvmStatic
            val toModel: (Row) -> Migration = { row ->
                Migration(
                    row.int("migration_id"),
                    row.string("version"),
                    row.int("batch_id"),
                    row.localDateTime("applied_at"),
                    row.intOrNull("migration_type"),
                    row.string("script_name"),
                    row.string("script_sql"),
                    row.intOrNull("rolled_back_id"),
                    row.stringOrNull("last_problem")
                )
            }
        }
    }

    @Language("SQL")
    val createTableSql = """
CREATE TABLE `migrations` (
  `migration_id`   INT(11)     NOT NULL AUTO_INCREMENT,
  `version`        VARCHAR(32) NOT NULL,
  `batch_id`       INT(11)     NOT NULL,
  `applied_at`     TIMESTAMP   NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `migration_type` TINYINT(1),
  `rolled_back_id` INT(11), # migration_id of roll back script
  `script_name`    VARCHAR(128),
  `script_sql`     MEDIUMTEXT,
  `last_problem`   MEDIUMTEXT,
  PRIMARY KEY (`migration_id`)
) DEFAULT CHARSET = utf8
"""

    @Language("SQL")
    val migrationSql = """
INSERT INTO migrations (
  version,
  batch_id,
  script_name,
  script_sql,
  migration_type,
  last_problem
) VALUES (
  :version,
  :batchId,
  :scriptName,
  :scriptSql,
  :migrationType,
  :lastProblem
)
"""
    var lastScriptName: String? = null
    var lastScriptSql: String? = null

    fun  invokeWith(action: (Session) -> T?): T? {
        return action.invoke(migrations.migrationSession)
    }

    fun getMigrationSql(scriptName: String, scriptSql: String, migrationType:Int? = null): SqlQuery {
        lastScriptName = scriptName
        lastScriptSql = scriptSql
        return sqlQuery(migrationSql, mapOf("version" to version, "batchId" to batchId, "scriptName" to scriptName, "scriptSql" to scriptSql, "migrationType" to migrationType))
    }

    fun insertUpMigrationAfter(scriptName: String, scriptSql: String, action: () -> Unit) {
        val sqlQuery = getMigrationSql(scriptName, scriptSql, 1)

        action.invoke()
        val transId = migrations.migrationSession.updateGetId(sqlQuery)

        // now need to mark all rollbacks of this script that they were reversed
        val rollBackScriptName = DbEntity.ROLLBACK.addSuffix( DbEntity.MIGRATION.removeSuffix(scriptName))
        val updateSql = sqlQuery("""
UPDATE migrations SET rolled_back_id = :transId WHERE (script_name = :scriptName OR script_name LIKE :scriptNameLike) AND version = :version AND migration_type = -1 AND rolled_back_id IS NULL
""", mapOf("transId" to transId, "version" to version, "scriptName" to rollBackScriptName, "scriptNameLike" to "$rollBackScriptName[%]"))
        migrations.migrationSession.execute(updateSql)
        if (!migrations.migrationSession.connection.autoCommit) {
            // commit changes so the last success is not lost on next failure
            migrations.migrationSession.connection.commit()
            migrations.migrationSession.connection.begin()
        }
    }

    fun insertDownMigrationAfter(scriptName: String, scriptSql: String, action: () -> Unit) {
        val sqlQuery = getMigrationSql(scriptName, scriptSql, -1)

        action.invoke()
        val transId = migrations.migrationSession.updateGetId(sqlQuery)

        // now need to mark all rollbacks of this script that they were reversed
        val rollBackScriptName = DbEntity.MIGRATION.addSuffix( DbEntity.ROLLBACK.removeSuffix(scriptName))
        val updateSql = sqlQuery("""
UPDATE migrations SET rolled_back_id = :transId WHERE (script_name = :scriptName OR script_name LIKE :scriptNameLike) AND version = :version AND migration_type = 1 AND rolled_back_id IS NULL
""", mapOf("transId" to transId, "version" to version, "scriptName" to rollBackScriptName, "scriptNameLike" to "$rollBackScriptName[%]"))
        migrations.migrationSession.execute(updateSql)
    }

    fun insertMigrationAfter(scriptName: String, scriptSql: String, action: () -> Unit) {
        val sqlQuery = getMigrationSql(scriptName, scriptSql)

        action.invoke()
        migrations.migrationSession.execute(sqlQuery)
    }

    fun getVersionBatches(): List {
        return migrations.migrationSession.list(sqlQuery("""
SELECT * FROM migrations
WHERE rolled_back_id IS NULL AND last_problem IS NULL
ORDER BY migration_id ASC
"""), Migration.toModel)
    }

    fun getVersionBatchesNameMap(): Map {
        val query = sqlQuery("""
SELECT * FROM migrations
WHERE rolled_back_id IS NULL AND last_problem IS NULL
ORDER BY migration_id ASC
""")
        val keyExtractor: (Row) -> String = { row ->
            row.string("script_name")
        }

        return migrations.migrationSession.hashMap(query, keyExtractor, Migration.toModel)
    }

    fun getAllVersionBatches(): List {
        return migrations.migrationSession.list(sqlQuery("""
SELECT * FROM migrations
ORDER BY migration_id ASC
"""), Migration.toModel)
    }

    fun withVersion(version: String): MigrationSession {
        return MigrationSession(batchId, version, migrations)
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy