Drop function if already exists and conflict
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
package fr.postgresjson.migration
|
package fr.postgresjson.migration
|
||||||
|
|
||||||
|
import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException
|
||||||
import fr.postgresjson.connexion.Connection
|
import fr.postgresjson.connexion.Connection
|
||||||
import fr.postgresjson.migration.Migration.Action
|
import fr.postgresjson.migration.Migration.Action
|
||||||
import fr.postgresjson.migration.Migration.Status
|
import fr.postgresjson.migration.Migration.Status
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.concurrent.CompletionException
|
||||||
import fr.postgresjson.definition.Function as DefinitionFunction
|
import fr.postgresjson.definition.Function as DefinitionFunction
|
||||||
|
|
||||||
data class Function(
|
data class Function(
|
||||||
@@ -34,7 +36,15 @@ data class Function(
|
|||||||
)
|
)
|
||||||
|
|
||||||
override fun up(): Status {
|
override fun up(): Status {
|
||||||
|
try {
|
||||||
connection.sendQuery(up.script)
|
connection.sendQuery(up.script)
|
||||||
|
} catch (e: CompletionException) {
|
||||||
|
val cause = e.cause
|
||||||
|
if (cause is GenericDatabaseException && cause.errorMessage.fields['C'] == "42P13") {
|
||||||
|
connection.sendQuery("drop function ${down.getDefinition()}")
|
||||||
|
connection.sendQuery(up.script)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this::class.java.classLoader.getResource("sql/migration/insertFunction.sql")!!.readText().let {
|
this::class.java.classLoader.getResource("sql/migration/insertFunction.sql")!!.readText().let {
|
||||||
connection.selectOne<MigrationEntity>(it, listOf(up.name, up.getDefinition(), up.script, down.script))?.let { function ->
|
connection.selectOne<MigrationEntity>(it, listOf(up.name, up.getDefinition(), up.script, down.script))?.let { function ->
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ data class Migrations private constructor(
|
|||||||
fun addFunction(newDefinition: DefinitionFunction, callback: (Function) -> Unit = {}): Migrations {
|
fun addFunction(newDefinition: DefinitionFunction, callback: (Function) -> Unit = {}): Migrations {
|
||||||
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) {
|
||||||
functions[newDefinition.name] = Function(newDefinition, newDefinition, connection).apply {
|
val oldDefinition = functions[newDefinition.name]?.up ?: newDefinition
|
||||||
|
functions[newDefinition.name] = Function(newDefinition, oldDefinition, connection).apply {
|
||||||
doExecute = Action.UP
|
doExecute = Action.UP
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class MigrationTest(): TestAbstract() {
|
|||||||
@Test
|
@Test
|
||||||
fun `run migrations force down`() {
|
fun `run migrations force down`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/real_migrations").toURI())
|
val resources = File(this::class.java.getResource("/sql/real_migrations").toURI())
|
||||||
val resourcesFunctions = File(this::class.java.getResource("/sql/function").toURI())
|
val resourcesFunctions = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
Migrations(listOf(resources, resourcesFunctions), connection).apply {
|
Migrations(listOf(resources, resourcesFunctions), connection).apply {
|
||||||
up().apply {
|
up().apply {
|
||||||
size `should be equal to` 6
|
size `should be equal to` 6
|
||||||
@@ -94,7 +94,7 @@ class MigrationTest(): TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `run functions migrations`() {
|
fun `run functions migrations`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
Migrations(resources, connection).apply {
|
Migrations(resources, connection).apply {
|
||||||
run().size `should be equal to` 5
|
run().size `should be equal to` 5
|
||||||
}
|
}
|
||||||
@@ -107,4 +107,26 @@ class MigrationTest(): TestAbstract() {
|
|||||||
Assertions.assertEquals(objTest!!.id, 3)
|
Assertions.assertEquals(objTest!!.id, 3)
|
||||||
Assertions.assertEquals(objTest.name, "test")
|
Assertions.assertEquals(objTest.name, "test")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `run functions migrations and drop if exist`() {
|
||||||
|
val resources = File(this::class.java.getResource("/sql/function/Test1").toURI())
|
||||||
|
Migrations(resources, connection).apply {
|
||||||
|
run().size `should be equal to` 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val objTest: RequesterTest.ObjTest? = Requester(connection)
|
||||||
|
.addFunction(resources)
|
||||||
|
.getFunction("test_function_duplicate")
|
||||||
|
.selectOne(listOf("test"))
|
||||||
|
|
||||||
|
Assertions.assertEquals(objTest!!.id, 3)
|
||||||
|
Assertions.assertEquals(objTest.name, "test")
|
||||||
|
|
||||||
|
|
||||||
|
val resources2 = File(this::class.java.getResource("/sql/function/Test2").toURI())
|
||||||
|
Migrations(resources2, connection).apply {
|
||||||
|
run().size `should be equal to` 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get function from file`() {
|
fun `get function from file`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val objTest: ObjTest? = Requester(connection)
|
val objTest: ObjTest? = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
.getFunction("test_function")
|
.getFunction("test_function")
|
||||||
@@ -48,7 +48,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call exec on function`() {
|
fun `call exec on function`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val result = Requester(connection)
|
val result = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
.getFunction("test_function")
|
.getFunction("test_function")
|
||||||
@@ -70,7 +70,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call sendQuery on function`() {
|
fun `call sendQuery on function`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val result = Requester(connection)
|
val result = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
.getFunction("function_void")
|
.getFunction("function_void")
|
||||||
@@ -81,7 +81,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call selectOne on function`() {
|
fun `call selectOne on function`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val obj: ObjTest = Requester(connection)
|
val obj: ObjTest = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
.getFunction("test_function")
|
.getFunction("test_function")
|
||||||
@@ -92,7 +92,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call selectOne on function with object`() {
|
fun `call selectOne on function with object`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val obj2 = ObjTest("original")
|
val obj2 = ObjTest("original")
|
||||||
val obj: ObjTest = Requester(connection)
|
val obj: ObjTest = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
@@ -116,7 +116,7 @@ class RequesterTest: TestAbstract() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call select (multiple) on function`() {
|
fun `call select (multiple) on function`() {
|
||||||
val resources = File(this::class.java.getResource("/sql/function").toURI())
|
val resources = File(this::class.java.getResource("/sql/function/Test").toURI())
|
||||||
val obj: List<ObjTest>? = Requester(connection)
|
val obj: List<ObjTest>? = Requester(connection)
|
||||||
.addFunction(resources)
|
.addFunction(resources)
|
||||||
.getFunction("test_function_multiple")
|
.getFunction("test_function_multiple")
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import java.io.File
|
|||||||
|
|
||||||
@TestInstance(PER_CLASS)
|
@TestInstance(PER_CLASS)
|
||||||
abstract class TestAbstract {
|
abstract class TestAbstract {
|
||||||
protected val connection = Connection(database = "test", username = "test", password = "test")
|
protected val connection = Connection(database = "test_json", username = "test", password = "test")
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun beforeAll() {
|
fun beforeAll() {
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
CREATE OR REPLACE FUNCTION test_function_duplicate (name text default 'plop', out result json)
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
result = json_build_object('id', 3, 'name', name);
|
||||||
|
END;
|
||||||
|
$$
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
CREATE OR REPLACE FUNCTION test_function_duplicate (name text default 'plop') returns text
|
||||||
|
LANGUAGE plpgsql
|
||||||
|
AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return name;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
Reference in New Issue
Block a user