WIP: Compiled SQL function #33
9
src/.editorconfig
Normal file
9
src/.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
tab_width = 4
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package fr.postgresjson.definition
|
package fr.postgresjson.definition
|
||||||
|
|
||||||
import fr.postgresjson.definition.Parameter.Direction.IN
|
import fr.postgresjson.definition.Parameter.Direction.IN
|
||||||
import fr.postgresjson.definition.parse.ScriptPart
|
|
||||||
import fr.postgresjson.definition.parse.trimSpace
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class Function(
|
class Function(
|
||||||
@@ -11,7 +9,7 @@ class Function(
|
|||||||
val returns: Returns,
|
val returns: Returns,
|
||||||
override val script: String,
|
override val script: String,
|
||||||
override val source: Path? = null,
|
override val source: Path? = null,
|
||||||
): Resource, ParametersInterface {
|
) : Resource, ParametersInterface {
|
||||||
|
|
||||||
// private fun <T> NextScript<T>.changeValue(block: (T) -> T): NextScript<T> {
|
// private fun <T> NextScript<T>.changeValue(block: (T) -> T): NextScript<T> {
|
||||||
// return NextScript(block(value), restOfScript)
|
// return NextScript(block(value), restOfScript)
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ class Parameter(
|
|||||||
override val type: ParameterType,
|
override val type: ParameterType,
|
||||||
val direction: Direction = Direction.IN,
|
val direction: Direction = Direction.IN,
|
||||||
val default: String? = null,
|
val default: String? = null,
|
||||||
): ParameterSimpleI {
|
) : ParameterSimpleI {
|
||||||
constructor(name: String?, type: ParameterType, direction: String = "IN", default: String? = null): this(
|
constructor(name: String?, type: ParameterType, direction: String = "IN", default: String? = null) : this(
|
||||||
name = name,
|
name = name,
|
||||||
type = type,
|
type = type,
|
||||||
direction = direction.let { Direction.valueOf(direction.uppercase(Locale.getDefault())) },
|
direction = direction.let { Direction.valueOf(direction.uppercase(Locale.getDefault())) },
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ sealed class Returns(
|
|||||||
class Primitive(
|
class Primitive(
|
||||||
definition: String,
|
definition: String,
|
||||||
isSetOf: Boolean,
|
isSetOf: Boolean,
|
||||||
): Returns(definition, isSetOf) {
|
) : Returns(definition, isSetOf) {
|
||||||
val name = definition
|
val name = definition
|
||||||
.trim('"')
|
.trim('"')
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ sealed class Returns(
|
|||||||
class PrimitiveList(
|
class PrimitiveList(
|
||||||
definition: String,
|
definition: String,
|
||||||
isSetOf: Boolean,
|
isSetOf: Boolean,
|
||||||
): Returns(definition, isSetOf) {
|
) : Returns(definition, isSetOf) {
|
||||||
val name = definition
|
val name = definition
|
||||||
.drop(2)
|
.drop(2)
|
||||||
.trim('"')
|
.trim('"')
|
||||||
@@ -25,16 +25,16 @@ sealed class Returns(
|
|||||||
definition: String,
|
definition: String,
|
||||||
isSetOf: Boolean,
|
isSetOf: Boolean,
|
||||||
val parameters: List<ParameterTable>,
|
val parameters: List<ParameterTable>,
|
||||||
): Returns(definition, isSetOf) {
|
) : Returns(definition, isSetOf) {
|
||||||
class ParameterTable(
|
class ParameterTable(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val type: ParameterType,
|
override val type: ParameterType,
|
||||||
): ParameterSimpleI
|
) : ParameterSimpleI
|
||||||
}
|
}
|
||||||
|
|
||||||
class Any(
|
class Any(
|
||||||
isSetOf: Boolean,
|
isSetOf: Boolean,
|
||||||
): Returns("any", isSetOf)
|
) : Returns("any", isSetOf)
|
||||||
|
|
||||||
class Void: Returns("void", false)
|
class Void : Returns("void", false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package fr.postgresjson.definition.parse
|
|||||||
|
|
||||||
import fr.postgresjson.definition.Function
|
import fr.postgresjson.definition.Function
|
||||||
import fr.postgresjson.definition.Parameter
|
import fr.postgresjson.definition.Parameter
|
||||||
import fr.postgresjson.definition.Returns.Void
|
|
||||||
import fr.postgresjson.definition.Parameter.Direction
|
import fr.postgresjson.definition.Parameter.Direction
|
||||||
import fr.postgresjson.definition.Parameter.Direction.IN
|
import fr.postgresjson.definition.Parameter.Direction.IN
|
||||||
import fr.postgresjson.definition.Parameter.Direction.INOUT
|
import fr.postgresjson.definition.Parameter.Direction.INOUT
|
||||||
@@ -10,6 +9,7 @@ import fr.postgresjson.definition.Parameter.Direction.OUT
|
|||||||
import fr.postgresjson.definition.ParameterType
|
import fr.postgresjson.definition.ParameterType
|
||||||
import fr.postgresjson.definition.Resource.ParseException
|
import fr.postgresjson.definition.Resource.ParseException
|
||||||
import fr.postgresjson.definition.Returns
|
import fr.postgresjson.definition.Returns
|
||||||
|
import fr.postgresjson.definition.Returns.Void
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.text.RegexOption.IGNORE_CASE
|
import kotlin.text.RegexOption.IGNORE_CASE
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@ internal fun parseFunction(script: String, source: Path? = null): Function {
|
|||||||
return Function(name, parameters, returns, script, source)
|
return Function(name, parameters, returns, script, source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Throws(FunctionNameMalformed::class)
|
@Throws(FunctionNameMalformed::class)
|
||||||
internal fun ScriptPart.getFunctionName(): NextScript<String> {
|
internal fun ScriptPart.getFunctionName(): NextScript<String> {
|
||||||
try {
|
try {
|
||||||
@@ -35,7 +34,7 @@ internal fun ScriptPart.getFunctionName(): NextScript<String> {
|
|||||||
throw FunctionNameMalformed(this, e)
|
throw FunctionNameMalformed(this, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal class FunctionNameMalformed(val script: ScriptPart, cause: Throwable? = null):
|
internal class FunctionNameMalformed(val script: ScriptPart, cause: Throwable? = null) :
|
||||||
ParseException("Function name is malformed", cause)
|
ParseException("Function name is malformed", cause)
|
||||||
|
|
||||||
@Throws(FunctionNotFound::class)
|
@Throws(FunctionNotFound::class)
|
||||||
@@ -54,7 +53,7 @@ internal fun ScriptPart.getFunctionOrProcedure(): NextScript<String> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class FunctionNotFound(val script: ScriptPart):
|
internal class FunctionNotFound(val script: ScriptPart) :
|
||||||
ParseException("Function not found in script")
|
ParseException("Function not found in script")
|
||||||
|
|
||||||
internal fun ScriptPart.getParameters(): NextScript<List<Parameter>> {
|
internal fun ScriptPart.getParameters(): NextScript<List<Parameter>> {
|
||||||
@@ -96,7 +95,7 @@ private fun ScriptPart.getParameterName(): NextScript<String> {
|
|||||||
throw ParameterNameMalformed(this, e)
|
throw ParameterNameMalformed(this, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private class ParameterNameMalformed(val script: ScriptPart, cause: Throwable):
|
private class ParameterNameMalformed(val script: ScriptPart, cause: Throwable) :
|
||||||
ParseException("Parameter name is malformed", cause)
|
ParseException("Parameter name is malformed", cause)
|
||||||
|
|
||||||
@Throws(ParameterTypeMalformed::class)
|
@Throws(ParameterTypeMalformed::class)
|
||||||
@@ -125,11 +124,12 @@ private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
|||||||
name = name.value.trim(),
|
name = name.value.trim(),
|
||||||
precision = precision.value,
|
precision = precision.value,
|
||||||
scale = scale.value
|
scale = scale.value
|
||||||
), fullType.nextScriptPart.restOfScript
|
),
|
||||||
|
fullType.nextScriptPart.restOfScript
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class ParameterTypeMalformed(val script: ScriptPart, cause: Throwable):
|
internal class ParameterTypeMalformed(val script: ScriptPart, cause: Throwable) :
|
||||||
ParseException("Parameter type is malformed", cause)
|
ParseException("Parameter type is malformed", cause)
|
||||||
|
|
||||||
@Throws(ParameterDefaultMalformed::class)
|
@Throws(ParameterDefaultMalformed::class)
|
||||||
@@ -146,7 +146,7 @@ private fun ScriptPart.getParameterDefault(): NextScript<String?> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ParameterDefaultMalformed(val script: ScriptPart):
|
private class ParameterDefaultMalformed(val script: ScriptPart) :
|
||||||
ParseException("Parameter default is malformed")
|
ParseException("Parameter default is malformed")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -156,5 +156,5 @@ internal fun ScriptPart.getReturns(): NextScript<Returns> {
|
|||||||
return NextScript(Void(), "")
|
return NextScript(Void(), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
class ParseError(message: String? = null, cause: Throwable? = null):
|
class ParseError(message: String? = null, cause: Throwable? = null) :
|
||||||
ParseException(message ?: "Parsing fail", cause)
|
ParseException(message ?: "Parsing fail", cause)
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ internal inline fun ScriptPart.change(block: String.() -> String): ScriptPart {
|
|||||||
return ScriptPart(restOfScript.run(block))
|
return ScriptPart(restOfScript.run(block))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
|
internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
|
||||||
val trimmed = restOfScript.trimStart { !it.isDigit() }
|
val trimmed = restOfScript.trimStart { !it.isDigit() }
|
||||||
val digits = trimmed.takeWhile { it.isDigit() }
|
val digits = trimmed.takeWhile { it.isDigit() }
|
||||||
@@ -136,8 +135,6 @@ internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
|
|||||||
return NextScript(digits.toIntOrNull(), restOfScript).trimSpace()
|
return NextScript(digits.toIntOrNull(), restOfScript).trimSpace()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal data class Status(
|
internal data class Status(
|
||||||
var doubleQuoted: Boolean = false, // "
|
var doubleQuoted: Boolean = false, // "
|
||||||
var simpleQuoted: Boolean = false, // '
|
var simpleQuoted: Boolean = false, // '
|
||||||
@@ -161,4 +158,4 @@ internal data class Context(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val nextChar: Char? get() = script.substring(index + 1).getOrNull(0)
|
val nextChar: Char? get() = script.substring(index + 1).getOrNull(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package fr.postgresjson.functionGenerator
|
package fr.postgresjson.functionGenerator
|
||||||
|
|
||||||
import fr.postgresjson.definition.Function
|
import fr.postgresjson.definition.Function
|
||||||
import fr.postgresjson.definition.Returns
|
|
||||||
import fr.postgresjson.definition.Parameter
|
import fr.postgresjson.definition.Parameter
|
||||||
import fr.postgresjson.definition.Parameter.Direction.IN
|
import fr.postgresjson.definition.Parameter.Direction.IN
|
||||||
import fr.postgresjson.definition.Parameter.Direction.INOUT
|
import fr.postgresjson.definition.Parameter.Direction.INOUT
|
||||||
import fr.postgresjson.definition.Parameter.Direction.OUT
|
import fr.postgresjson.definition.Parameter.Direction.OUT
|
||||||
|
import fr.postgresjson.definition.Returns
|
||||||
import fr.postgresjson.utils.searchSqlFiles
|
import fr.postgresjson.utils.searchSqlFiles
|
||||||
import fr.postgresjson.utils.toCamelCase
|
import fr.postgresjson.utils.toCamelCase
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
|
|||||||
@@ -9,26 +9,30 @@ import fr.postgresjson.serializer.toTypeReference
|
|||||||
import io.kotest.core.spec.style.StringSpec
|
import io.kotest.core.spec.style.StringSpec
|
||||||
import io.kotest.matchers.nulls.shouldBeNull
|
import io.kotest.matchers.nulls.shouldBeNull
|
||||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||||
import org.amshove.kluent.`should be equal to`
|
|
||||||
import org.junit.jupiter.api.assertThrows
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.reflect.full.hasAnnotation
|
import kotlin.reflect.full.hasAnnotation
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
import org.amshove.kluent.`should be equal to`
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
|
||||||
class ConnectionTest : StringSpec({
|
class ConnectionTest: StringSpec({
|
||||||
val connection = TestConnection()
|
val connection = TestConnection()
|
||||||
|
|
||||||
@SqlSerializable
|
@SqlSerializable
|
||||||
class ObjTest(val name: String, val id: UUID = UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00"))
|
class ObjTest(val name: String, val id: UUID = UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00"))
|
||||||
|
|
||||||
@SqlSerializable
|
@SqlSerializable
|
||||||
class ObjTest2(val id: UUID, val title: String, var test: ObjTest?)
|
class ObjTest2(val id: UUID, val title: String, var test: ObjTest?)
|
||||||
|
|
||||||
@SqlSerializable
|
@SqlSerializable
|
||||||
class ObjTest3(val id: UUID, val first: String, var second: String, var third: Int)
|
class ObjTest3(val id: UUID, val first: String, var second: String, var third: Int)
|
||||||
|
|
||||||
@SqlSerializable
|
@SqlSerializable
|
||||||
class ParameterObject(var third: String)
|
class ParameterObject(var third: String)
|
||||||
|
|
||||||
@SqlSerializable
|
@SqlSerializable
|
||||||
class ObjTestWithParameterObject(val id: UUID, var first: ParameterObject, var second: ParameterObject)
|
class ObjTestWithParameterObject(val id: UUID, var first: ParameterObject, var second: ParameterObject)
|
||||||
class ObjTest4
|
class ObjTest4
|
||||||
@@ -112,7 +116,7 @@ class ConnectionTest : StringSpec({
|
|||||||
"test call request without args" {
|
"test call request without args" {
|
||||||
val result: ObjTest? = connection.execute(
|
val result: ObjTest? = connection.execute(
|
||||||
"select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', 'myName')",
|
"select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', 'myName')",
|
||||||
object : TypeReference<ObjTest>() {}
|
object: TypeReference<ObjTest>() {}
|
||||||
) {
|
) {
|
||||||
assertEquals("myName", this.deserialize<ObjTest>()?.name)
|
assertEquals("myName", this.deserialize<ObjTest>()?.name)
|
||||||
}
|
}
|
||||||
@@ -121,7 +125,7 @@ class ConnectionTest : StringSpec({
|
|||||||
}
|
}
|
||||||
|
|
||||||
"test call request return null" {
|
"test call request return null" {
|
||||||
val result: ObjTest? = connection.execute("select null;", object : TypeReference<ObjTest>() {})
|
val result: ObjTest? = connection.execute("select null;", object: TypeReference<ObjTest>() {})
|
||||||
result.shouldBeNull()
|
result.shouldBeNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +141,7 @@ class ConnectionTest : StringSpec({
|
|||||||
)
|
)
|
||||||
|
|
||||||
assertThrows<DataNotFoundException> {
|
assertThrows<DataNotFoundException> {
|
||||||
execute("select * from test where false;", object : TypeReference<ObjTest>() {})
|
execute("select * from test where false;", object: TypeReference<ObjTest>() {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user