refactoring: definition.Function
This commit is contained in:
@@ -40,7 +40,7 @@ class Requester (
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addFunction(sql: String): Requester {
|
fun addFunction(sql: String): Requester {
|
||||||
DefinitionFunction.build(sql).forEach {
|
DefinitionFunction(sql).let {
|
||||||
functions[it.name] = Function(it, connection)
|
functions[it.name] = Function(it, connection)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
|
|||||||
@@ -4,26 +4,22 @@ import java.io.File
|
|||||||
|
|
||||||
|
|
||||||
open class Function (
|
open class Function (
|
||||||
override val name: String,
|
override val script: String
|
||||||
override val script: String,
|
|
||||||
override val parameters: List<Parameter>
|
|
||||||
) : Resource, ParametersInterface {
|
) : Resource, ParametersInterface {
|
||||||
|
override val name: String
|
||||||
|
override val parameters: List<Parameter>
|
||||||
override var source: File? = null
|
override var source: File? = null
|
||||||
|
|
||||||
companion object {
|
init {
|
||||||
fun build(source: File): List<Function> {
|
|
||||||
return build(source.readText())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun build(functionContent: String): List<Function> {
|
|
||||||
val functionRegex = """create .*(procedure|function) *(?<name>[^(\s]+)\s*\((?<params>(\s*((IN|OUT|INOUT|VARIADIC)?\s+)?([^\s,)]+\s+)?([^\s,)]+)(\s+(?:default\s|=)\s*[^\s,)]+)?\s*(,|(?=\))))*)\) *(?<return>RETURNS *[^ ]+)?"""
|
val functionRegex = """create .*(procedure|function) *(?<name>[^(\s]+)\s*\((?<params>(\s*((IN|OUT|INOUT|VARIADIC)?\s+)?([^\s,)]+\s+)?([^\s,)]+)(\s+(?:default\s|=)\s*[^\s,)]+)?\s*(,|(?=\))))*)\) *(?<return>RETURNS *[^ ]+)?"""
|
||||||
.toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
|
.toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
|
||||||
|
|
||||||
val paramsRegex = """\s*(?<param>((?<direction>IN|OUT|INOUT|VARIADIC)?\s+)?(?<name>[^\s,)]+\s+)?(?<type>[^\s,)]+)(\s+(?<default>default\s|=)\s*[^\s,)]+)?)\s*(,|$)"""
|
val paramsRegex = """\s*(?<param>((?<direction>IN|OUT|INOUT|VARIADIC)?\s+)?(?<name>[^\s,)]+\s+)?(?<type>[^\s,)]+)(\s+(?<default>default\s|=)\s*[^\s,)]+)?)\s*(,|$)"""
|
||||||
.toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
|
.toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE))
|
||||||
|
|
||||||
return functionRegex.findAll(functionContent).map { queryMatch ->
|
val queryMatch = functionRegex.find(script)
|
||||||
val functionName = queryMatch.groups["name"]?.value?.trim()
|
if (queryMatch !== null) {
|
||||||
|
val functionName = queryMatch.groups.get("name")?.value?.trim()
|
||||||
val functionParameters = queryMatch.groups["params"]?.value?.trim()
|
val functionParameters = queryMatch.groups["params"]?.value?.trim()
|
||||||
val returns = queryMatch.groups["return"]?.value?.trim()
|
val returns = queryMatch.groups["return"]?.value?.trim()
|
||||||
|
|
||||||
@@ -40,9 +36,22 @@ open class Function (
|
|||||||
} else {
|
} else {
|
||||||
listOf()
|
listOf()
|
||||||
}
|
}
|
||||||
|
this.name = functionName!!
|
||||||
|
this.parameters = parameters
|
||||||
|
} else {
|
||||||
|
throw FunctionNotFound()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
abstract class ParseException(message: String, cause: Throwable? = null): Exception(message, cause)
|
||||||
|
class FunctionNotFound(cause: Throwable? = null): ParseException("Function not found in script", cause)
|
||||||
|
|
||||||
Function(functionName!!, functionContent, parameters)
|
companion object {
|
||||||
}.toList()
|
fun build(source: File): List<Function> {
|
||||||
|
return source.readText()
|
||||||
|
.split("CREATE +(OR REPLACE +)?(PROCEDURE|FUNCTION)".toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.MULTILINE)))
|
||||||
|
.map {
|
||||||
|
Function("CREATE OR REPLACE FUNCTION $it")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,19 @@ import fr.postgresjson.connexion.Connection
|
|||||||
import fr.postgresjson.definition.Function as DefinitionFunction
|
import fr.postgresjson.definition.Function as DefinitionFunction
|
||||||
|
|
||||||
class Function(
|
class Function(
|
||||||
private val up: DefinitionFunction,
|
val up: DefinitionFunction,
|
||||||
private val down: DefinitionFunction,
|
val down: DefinitionFunction,
|
||||||
private val connection: Connection
|
private val connection: Connection
|
||||||
): Migration {
|
): Migration {
|
||||||
|
val name = up.name
|
||||||
enum class Status(i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) }
|
enum class Status(i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) }
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (up.name !== down.name) {
|
||||||
|
throw Exception("UP and DOWN migration must be the same")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun up(): Int {
|
override fun up(): Int {
|
||||||
connection.exec(up.script)
|
connection.exec(up.script)
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ interface Migration {
|
|||||||
class Migrations(directory: File, private val connection: Connection): Migration {
|
class Migrations(directory: File, private val connection: Connection): Migration {
|
||||||
private val queries: MutableList<Query> = mutableListOf()
|
private val queries: MutableList<Query> = mutableListOf()
|
||||||
private val functions: MutableMap<String, Function> = mutableMapOf()
|
private val functions: MutableMap<String, Function> = mutableMapOf()
|
||||||
|
private var initialized = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
directory.walk().filter {
|
directory.walk().filter {
|
||||||
@@ -26,15 +27,15 @@ class Migrations(directory: File, private val connection: Connection): Migration
|
|||||||
it.isFile
|
it.isFile
|
||||||
}.forEach { file ->
|
}.forEach { file ->
|
||||||
if (file.name.endsWith(".up.sql")) {
|
if (file.name.endsWith(".up.sql")) {
|
||||||
val up = file.readText()
|
file.path.substring(0, file.path.size - 7).let {
|
||||||
val down = file.path.substring(0, file.path.size - 7).let {
|
|
||||||
try {
|
try {
|
||||||
File("$it.down.sql").readText()
|
val down = File("$it.down.sql").readText()
|
||||||
|
val up = file.readText()
|
||||||
|
addQuery(file.name, up, down)
|
||||||
} catch (e: FileNotFoundException) {
|
} catch (e: FileNotFoundException) {
|
||||||
throw DownMigrationNotDefined("$it.down.sql", e)
|
throw DownMigrationNotDefined("$it.down.sql", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addQuery(up, down)
|
|
||||||
} else if (file.name.endsWith(".down.sql")) {
|
} else if (file.name.endsWith(".down.sql")) {
|
||||||
// Nothing
|
// Nothing
|
||||||
} else {
|
} else {
|
||||||
@@ -53,14 +54,14 @@ class Migrations(directory: File, private val connection: Connection): Migration
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun addFunction(sql: String): Migrations {
|
fun addFunction(sql: String): Migrations {
|
||||||
DefinitionFunction.build(sql).forEach {
|
DefinitionFunction(sql).let {
|
||||||
functions[it.name] = Function(it, it, connection)
|
functions[it.name] = Function(it, it, connection)
|
||||||
}
|
}
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addQuery(up: String, down: String): Migrations {
|
fun addQuery(name: String, up: String, down: String): Migrations {
|
||||||
queries.add(Query(up, down, connection))
|
queries.add(Query(name, up, down, connection))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package fr.postgresjson.migration
|
|||||||
import fr.postgresjson.connexion.Connection
|
import fr.postgresjson.connexion.Connection
|
||||||
|
|
||||||
class Query(
|
class Query(
|
||||||
private val up: String,
|
val name: String,
|
||||||
private val down: String,
|
val up: String,
|
||||||
|
val down: String,
|
||||||
private val connection: Connection
|
private val connection: Connection
|
||||||
): Migration {
|
): Migration {
|
||||||
enum class Status(i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) }
|
enum class Status(i: Int) { OK(2), UP_FAIL(0), DOWN_FAIL(1) }
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
-- grant all privileges on database test to test;
|
-- grant all privileges on database test to test;
|
||||||
-- ALTER SCHEMA public owner to test;
|
-- ALTER SCHEMA public owner to test;
|
||||||
|
|
||||||
|
drop schema IF EXISTS public cascade;
|
||||||
|
create schema if not exists public;
|
||||||
|
|
||||||
create table if not exists test
|
create table if not exists test
|
||||||
(
|
(
|
||||||
id serial not null
|
id serial not null
|
||||||
|
|||||||
Reference in New Issue
Block a user