Fix/function with same name #34
@@ -3,6 +3,20 @@
|
|||||||
## Gradle
|
## Gradle
|
||||||
```kotlin
|
```kotlin
|
||||||
// build.gradle.kts
|
// build.gradle.kts
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
maven { url = uri("https://jitpack.io") }
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath("com.github.flecomte:postgres-json:+")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven { url = uri("https://jitpack.io") }
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.github.flecomte:postgres-json:+")
|
implementation("com.github.flecomte:postgres-json:+")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class Function(val definition: Function, override val connection: Connection) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun compileArgs(values: Map<String, Any?>): String {
|
private fun compileArgs(values: Map<String, Any?>): String {
|
||||||
val parameters = definition.getParametersIndexedByName()
|
val parameters = definition.parametersIndexedByName
|
||||||
val placeholders = values
|
val placeholders = values
|
||||||
.filter { entry ->
|
.filter { entry ->
|
||||||
val parameter = parameters[entry.key] ?: parameters["_" + entry.key] ?: error("Parameter ${entry.key} of function ${definition.name} not exist")
|
val parameter = parameters[entry.key] ?: parameters["_" + entry.key] ?: error("Parameter ${entry.key} of function ${definition.name} not exist")
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ class Requester(
|
|||||||
|
|
||||||
fun getQuery(path: String): Query = queries[path] ?: throw NoQueryDefined(path)
|
fun getQuery(path: String): Query = queries[path] ?: throw NoQueryDefined(path)
|
||||||
|
|
||||||
|
fun <A> inTransaction(block: Requester.() -> A?): A? = connection.inTransaction {
|
||||||
|
this@Requester.block()
|
||||||
|
}
|
||||||
|
|
||||||
class NoFunctionDefined(name: String) : Exception("No function defined for $name")
|
class NoFunctionDefined(name: String) : Exception("No function defined for $name")
|
||||||
class NoQueryDefined(path: String) : Exception("No query defined in $path")
|
class NoQueryDefined(path: String) : Exception("No query defined in $path")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package fr.postgresjson.definition
|
package fr.postgresjson.definition
|
||||||
|
|
||||||
|
import fr.postgresjson.utils.Algorithm.MD5
|
||||||
|
import fr.postgresjson.utils.hash
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class Function(
|
class Function(
|
||||||
@@ -48,19 +50,26 @@ class Function(
|
|||||||
|
|
||||||
class FunctionNotFound(cause: Throwable? = null) : Resource.ParseException("Function not found in script", cause)
|
class FunctionNotFound(cause: Throwable? = null) : Resource.ParseException("Function not found in script", cause)
|
||||||
|
|
||||||
fun getDefinition(): String {
|
val definition: String
|
||||||
return parameters
|
get() {
|
||||||
.filter { it.direction == Parameter.Direction.IN }
|
return parameters
|
||||||
.joinToString(", ") { "${it.name} ${it.type}" }
|
.filter { it.direction == Parameter.Direction.IN }
|
||||||
.let { "$name ($it)" }
|
.joinToString(", ") { "${it.name} ${it.type}" }
|
||||||
}
|
.let { "$name ($it)" }
|
||||||
|
}
|
||||||
|
|
||||||
fun getParametersIndexedByName(): Map<String, Parameter> {
|
val definitionHash: String
|
||||||
return parameters.associateBy { it.name }
|
get() {
|
||||||
}
|
return definition.hash(MD5)
|
||||||
|
}
|
||||||
|
|
||||||
|
val parametersIndexedByName: Map<String, Parameter>
|
||||||
|
get() {
|
||||||
|
return parameters.associateBy { it.name }
|
||||||
|
}
|
||||||
|
|
||||||
infix fun `has same definition`(other: Function): Boolean {
|
infix fun `has same definition`(other: Function): Boolean {
|
||||||
return other.getDefinition() == this.getDefinition()
|
return other.definition == this.definition
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun `is different from`(other: Function): Boolean {
|
infix fun `is different from`(other: Function): Boolean {
|
||||||
|
|||||||
@@ -43,14 +43,14 @@ data class Function(
|
|||||||
} catch (e: CompletionException) {
|
} catch (e: CompletionException) {
|
||||||
val cause = e.cause
|
val cause = e.cause
|
||||||
if (cause is GenericDatabaseException && cause.errorMessage.fields['C'] == "42P13") {
|
if (cause is GenericDatabaseException && cause.errorMessage.fields['C'] == "42P13") {
|
||||||
connection.sendQuery("drop function ${down.getDefinition()}")
|
connection.sendQuery("drop function ${down.definition}")
|
||||||
connection.sendQuery(up.script)
|
connection.sendQuery(up.script)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this::class.java.classLoader
|
this::class.java.classLoader
|
||||||
.getResource("sql/migration/insertFunction.sql")!!.readText()
|
.getResource("sql/migration/insertFunction.sql")!!.readText()
|
||||||
.let { connection.selectOne<MigrationEntity>(it, listOf(up.name, up.getDefinition(), up.script, down.script)) }
|
.let { connection.selectOne<MigrationEntity>(it, listOf(up.name, up.definition, up.script, down.script)) }
|
||||||
?.let { function ->
|
?.let { function ->
|
||||||
executedAt = function.executedAt
|
executedAt = function.executedAt
|
||||||
doExecute = Action.OK
|
doExecute = Action.OK
|
||||||
|
|||||||
@@ -133,17 +133,17 @@ class Migrations private constructor(
|
|||||||
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 = {}): Migrations {
|
||||||
val currentFunction = functions[newDefinition.name]
|
val currentFunction = functions[newDefinition.definitionHash]
|
||||||
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.definitionHash]?.up ?: newDefinition
|
||||||
functions[newDefinition.name] = Function(newDefinition, oldDefinition, connection).apply {
|
functions[newDefinition.definitionHash] = Function(newDefinition, oldDefinition, connection).apply {
|
||||||
doExecute = Action.UP
|
doExecute = Action.UP
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
functions[newDefinition.name]?.doExecute = Action.OK
|
functions[newDefinition.definitionHash]?.doExecute = Action.OK
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(functions[newDefinition.name]!!)
|
callback(functions[newDefinition.definitionHash]!!)
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -215,7 +215,7 @@ class Migrations private constructor(
|
|||||||
return list.toMap()
|
return list.toMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun down(force: Boolean = false): Map<String, Status> {
|
fun down(force: Boolean = false): Map<String, Status> {
|
||||||
val list: MutableMap<String, Status> = mutableMapOf()
|
val list: MutableMap<String, Status> = mutableMapOf()
|
||||||
migrationsScripts.forEach {
|
migrationsScripts.forEach {
|
||||||
it.value.let { query ->
|
it.value.let { query ->
|
||||||
|
|||||||
12
src/main/kotlin/fr/postgresjson/utils/md5.kt
Normal file
12
src/main/kotlin/fr/postgresjson/utils/md5.kt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package fr.postgresjson.utils
|
||||||
|
|
||||||
|
import java.math.BigInteger
|
||||||
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
internal enum class Algorithm(name: String) {
|
||||||
|
MD5("MD5")
|
||||||
|
}
|
||||||
|
internal fun String.hash(algorithm: Algorithm): String {
|
||||||
|
val md = MessageDigest.getInstance(algorithm.name)
|
||||||
|
return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0')
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user