WIP: Compiled SQL function #33

Draft
flecomte wants to merge 37 commits from compiled_sql_function into master
4 changed files with 30 additions and 51 deletions
Showing only changes of commit f8f3273f18 - Show all commits

View File

@@ -77,16 +77,6 @@ data class Function(
} }
} }
override fun test(): Status {
connection.inTransaction {
up()
down()
sendQuery("ROLLBACK")
}
return Status.OK
}
fun copy(): Function = this fun copy(): Function = this
.copy(up = up, down = down, connection = connection, executedAt = executedAt) .copy(up = up, down = down, connection = connection, executedAt = executedAt)
.also { it.doExecute = this.doExecute } .also { it.doExecute = this.doExecute }

View File

@@ -26,13 +26,12 @@ interface Migration {
var doExecute: Action? var doExecute: Action?
fun up(): Status fun up(): Status
fun down(): Status fun down(): Status
fun test(): Status
enum class Status(val i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) } enum class Status(val i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) }
enum class Action { OK, UP, DOWN } enum class Action { OK, UP, DOWN }
} }
class Migrations private constructor( class MigrationExecutor private constructor(
private val connection: Connection, private val connection: Connection,
private val migrationsScripts: MutableMap<String, MigrationScript> = mutableMapOf(), private val migrationsScripts: MutableMap<String, MigrationScript> = mutableMapOf(),
private val functions: MutableMap<String, Function> = mutableMapOf() private val functions: MutableMap<String, Function> = mutableMapOf()
@@ -52,8 +51,8 @@ class Migrations private constructor(
migrationsScripts.clear() migrationsScripts.clear()
functions.clear() functions.clear()
getMigrationFromDB() addMigrationFromDB()
getMigrationFromDirectory(directories) addMigrationFromDirectory(directories)
migrationsScripts.forEach { (_, query) -> migrationsScripts.forEach { (_, query) ->
if (query.doExecute === null) { if (query.doExecute === null) {
@@ -73,7 +72,7 @@ class Migrations private constructor(
/** /**
* Get all migration from DB * Get all migration from DB
*/ */
private fun getMigrationFromDB() { private fun addMigrationFromDB() {
this::class.java.classLoader.getResource("sql/migration/findAllFunction.sql")!!.readText().let { this::class.java.classLoader.getResource("sql/migration/findAllFunction.sql")!!.readText().let {
connection.execute(it, object : TypeReference<List<MigrationEntity>>() {}) connection.execute(it, object : TypeReference<List<MigrationEntity>>() {})
?.map { function -> ?.map { function ->
@@ -92,16 +91,16 @@ class Migrations private constructor(
/** /**
* Get all migration from multiples Directories * Get all migration from multiples Directories
*/ */
private fun getMigrationFromDirectory(directory: List<URI>) { private fun addMigrationFromDirectory(directories: List<URI>) {
directory.forEach { directories.forEach {
getMigrationFromDirectory(it) addMigrationFromDirectory(it)
} }
} }
/** /**
* Get all migration from Directory * Get all migration from Directory
*/ */
private fun getMigrationFromDirectory(directory: URI) { private fun addMigrationFromDirectory(directory: URI) {
val downs: MutableMap<String, DefinitionMigration> = mutableMapOf() val downs: MutableMap<String, DefinitionMigration> = mutableMapOf()
directory.searchSqlFiles().apply { directory.searchSqlFiles().apply {
@@ -131,7 +130,7 @@ class Migrations private constructor(
internal class DownMigrationNotDefined(path: String, cause: FileNotFoundException? = null) : internal class DownMigrationNotDefined(path: String, cause: FileNotFoundException? = null) :
Throwable("The file $path was not found", cause) Throwable("The file $path was not found", cause)
fun addFunction(newDefinition: DefinitionFunction, callback: (Function) -> Unit = {}): Migrations { fun addFunction(newDefinition: DefinitionFunction, callback: (Function) -> Unit = {}): MigrationExecutor {
val currentFunction = functions[newDefinition.name] val currentFunction = functions[newDefinition.name]
if (currentFunction === null || currentFunction `is different from` newDefinition) { if (currentFunction === null || currentFunction `is different from` newDefinition) {
val oldDefinition = functions[newDefinition.name]?.up ?: newDefinition val oldDefinition = functions[newDefinition.name]?.up ?: newDefinition
@@ -147,15 +146,15 @@ class Migrations private constructor(
return this return this
} }
fun addFunction(sql: String): Migrations { fun addFunction(sql: String): MigrationExecutor {
addFunction(DefinitionFunction(sql)) addFunction(DefinitionFunction(sql))
return this return this
} }
fun addMigrationScript(up: DefinitionMigration, down: DefinitionMigration, callback: (MigrationScript) -> Unit = {}): Migrations = fun addMigrationScript(up: DefinitionMigration, down: DefinitionMigration, callback: (MigrationScript) -> Unit = {}): MigrationExecutor =
addMigrationScript(up.name, up.script, down.script, callback) addMigrationScript(up.name, up.script, down.script, callback)
fun addMigrationScript(name: String, up: String, down: String, callback: (MigrationScript) -> Unit = {}): Migrations { fun addMigrationScript(name: String, up: String, down: String, callback: (MigrationScript) -> Unit = {}): MigrationExecutor {
if (migrationsScripts[name] === null) { if (migrationsScripts[name] === null) {
migrationsScripts[name] = MigrationScript(name, up, down, connection).apply { migrationsScripts[name] = MigrationScript(name, up, down, connection).apply {
doExecute = Action.UP doExecute = Action.UP
@@ -296,7 +295,7 @@ class Migrations private constructor(
return list.toMap() return list.toMap()
} }
private fun copy(): Migrations { private fun copy(): MigrationExecutor {
val queriesCopy = migrationsScripts.map { val queriesCopy = migrationsScripts.map {
it.key to it.value.copy() it.key to it.value.copy()
}.toMap().toMutableMap() }.toMap().toMutableMap()
@@ -305,7 +304,7 @@ class Migrations private constructor(
it.key to it.value.copy() it.key to it.value.copy()
}.toMap().toMutableMap() }.toMap().toMutableMap()
return Migrations(connection, queriesCopy, functionsCopy) return MigrationExecutor(connection, queriesCopy, functionsCopy)
} }
fun status(): Map<String, Int> { fun status(): Map<String, Int> {

View File

@@ -19,8 +19,8 @@ data class MigrationScript(
return try { return try {
connection.sendQuery(up) connection.sendQuery(up)
this::class.java.classLoader.getResource("sql/migration/insertHistory.sql")!!.readText().let { this::class.java.classLoader.getResource("sql/migration/insertHistory.sql")!!.readText().let { sqlScript ->
connection.execute<MigrationEntity>(it, listOf(name, up, down))?.let { query -> connection.execute<MigrationEntity>(sqlScript, listOf(name, up, down))?.let { query ->
executedAt = query.executedAt executedAt = query.executedAt
doExecute = Action.OK doExecute = Action.OK
} ?: error("No migration executed") } ?: error("No migration executed")
@@ -42,16 +42,6 @@ data class MigrationScript(
return Status.OK return Status.OK
} }
override fun test(): Status {
connection.inTransaction {
up()
down()
sendQuery("ROLLBACK")
}
return Status.OK
}
fun copy(): MigrationScript { fun copy(): MigrationScript {
return this.copy(name = name, up = up, down = down, connection = connection, executedAt = executedAt).also { return this.copy(name = name, up = up, down = down, connection = connection, executedAt = executedAt).also {
it.doExecute = this.doExecute it.doExecute = this.doExecute

View File

@@ -3,7 +3,7 @@ package fr.postgresjson
import fr.postgresjson.connexion.Requester import fr.postgresjson.connexion.Requester
import fr.postgresjson.connexion.execute import fr.postgresjson.connexion.execute
import fr.postgresjson.migration.Migration import fr.postgresjson.migration.Migration
import fr.postgresjson.migration.Migrations import fr.postgresjson.migration.MigrationExecutor
import org.amshove.kluent.invoking import org.amshove.kluent.invoking
import org.amshove.kluent.`should be equal to` import org.amshove.kluent.`should be equal to`
import org.amshove.kluent.`should contain` import org.amshove.kluent.`should contain`
@@ -20,7 +20,7 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run up query`() { fun `run up query`() {
val resources = this::class.java.getResource("/sql/migrations")!!.toURI() val resources = this::class.java.getResource("/sql/migrations")!!.toURI()
val m = Migrations(connection, resources) val m = MigrationExecutor(connection, resources)
m.up().apply { m.up().apply {
this `should contain` Pair("1", Migration.Status.OK) this `should contain` Pair("1", Migration.Status.OK)
size `should be equal to` 1 size `should be equal to` 1
@@ -33,14 +33,14 @@ class MigrationTest : TestAbstract() {
fun `migration up Query should throw error if no down`() { fun `migration up Query should throw error if no down`() {
val resources = this::class.java.getResource("/sql/migration_without_down")!!.toURI() val resources = this::class.java.getResource("/sql/migration_without_down")!!.toURI()
invoking { invoking {
Migrations(resources, connection) MigrationExecutor(resources, connection)
} shouldThrow Migrations.DownMigrationNotDefined::class } shouldThrow MigrationExecutor.DownMigrationNotDefined::class
} }
@Test @Test
fun `run forced down query`() { fun `run forced down query`() {
val resources = this::class.java.getResource("/sql/migrations")!!.toURI() val resources = this::class.java.getResource("/sql/migrations")!!.toURI()
val m = Migrations(resources, connection) val m = MigrationExecutor(resources, connection)
repeat(3) { repeat(3) {
m.down(true).apply { m.down(true).apply {
this `should contain` Pair("1", Migration.Status.OK) this `should contain` Pair("1", Migration.Status.OK)
@@ -52,10 +52,10 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run dry migrations`() { fun `run dry migrations`() {
val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI() val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI()
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
runDry().size `should be equal to` 2 runDry().size `should be equal to` 2
} }
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
runDry().size `should be equal to` 2 runDry().size `should be equal to` 2
} }
} }
@@ -63,7 +63,7 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run dry migrations launch twice`() { fun `run dry migrations launch twice`() {
val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI() val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI()
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
runDry().size `should be equal to` 2 runDry().size `should be equal to` 2
runDry().size `should be equal to` 2 runDry().size `should be equal to` 2
} }
@@ -72,7 +72,7 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run migrations`() { fun `run migrations`() {
val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI() val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI()
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
run().apply { run().apply {
size `should be equal to` 1 size `should be equal to` 1
} }
@@ -83,12 +83,12 @@ class MigrationTest : TestAbstract() {
fun `run migrations force down`() { fun `run migrations force down`() {
val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI() val resources = this::class.java.getResource("/sql/real_migrations")!!.toURI()
val resourcesFunctions = this::class.java.getResource("/sql/function/Test")!!.toURI() val resourcesFunctions = this::class.java.getResource("/sql/function/Test")!!.toURI()
Migrations(listOf(resources, resourcesFunctions), connection).apply { MigrationExecutor(listOf(resources, resourcesFunctions), connection).apply {
up().apply { up().apply {
size `should be equal to` 6 size `should be equal to` 6
} }
} }
Migrations(listOf(resources, resourcesFunctions), connection).apply { MigrationExecutor(listOf(resources, resourcesFunctions), connection).apply {
forceAllDown().apply { forceAllDown().apply {
size `should be equal to` 6 size `should be equal to` 6
} }
@@ -98,7 +98,7 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run functions migrations`() { fun `run functions migrations`() {
val resources = this::class.java.getResource("/sql/function/Test")!!.toURI() val resources = this::class.java.getResource("/sql/function/Test")!!.toURI()
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
run().size `should be equal to` 5 run().size `should be equal to` 5
} }
@@ -114,7 +114,7 @@ class MigrationTest : TestAbstract() {
@Test @Test
fun `run functions migrations and drop if exist`() { fun `run functions migrations and drop if exist`() {
val resources = this::class.java.getResource("/sql/function/Test1")!!.toURI() val resources = this::class.java.getResource("/sql/function/Test1")!!.toURI()
Migrations(resources, connection).apply { MigrationExecutor(resources, connection).apply {
run().size `should be equal to` 1 run().size `should be equal to` 1
} }
@@ -126,7 +126,7 @@ class MigrationTest : TestAbstract() {
Assertions.assertEquals(objTest.name, "test") Assertions.assertEquals(objTest.name, "test")
val resources2 = this::class.java.getResource("/sql/function/Test2")!!.toURI() val resources2 = this::class.java.getResource("/sql/function/Test2")!!.toURI()
Migrations(resources2, connection).apply { MigrationExecutor(resources2, connection).apply {
run().size `should be equal to` 1 run().size `should be equal to` 1
} }
} }