Parse Function Returns
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
val containerAlwaysOn: String by project
|
||||
val disableLint: String by project
|
||||
val projectName = "postgres-json"
|
||||
val projectName: String by project
|
||||
|
||||
plugins {
|
||||
jacoco
|
||||
@@ -87,7 +87,7 @@ val sourcesJar by tasks.creating(Jar::class) {
|
||||
|
||||
apply(plugin = "docker-compose")
|
||||
dockerCompose {
|
||||
setProjectName(projectName)
|
||||
setProjectName(projectName.toString())
|
||||
setProperty("useComposeFiles", listOf("docker-compose.yml"))
|
||||
setProperty("stopContainers", !containerAlwaysOn.toBoolean())
|
||||
isRequiredBy(project.tasks.test)
|
||||
@@ -96,7 +96,7 @@ dockerCompose {
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = projectName
|
||||
name = projectName.toString()
|
||||
url = uri("https://maven.pkg.github.com/flecomte/postgres-json")
|
||||
credentials {
|
||||
username = System.getenv("GITHUB_USERNAME")
|
||||
@@ -106,7 +106,7 @@ publishing {
|
||||
}
|
||||
|
||||
publications {
|
||||
create<MavenPublication>(projectName) {
|
||||
create<MavenPublication>(projectName.toString()) {
|
||||
from(components["java"])
|
||||
artifact(sourcesJar)
|
||||
}
|
||||
|
||||
@@ -7,4 +7,5 @@ systemProp.sonar.java.coveragePlugin=jacoco
|
||||
systemProp.sonar.coverage.jacoco.xmlReportPaths=build/reports/jacoco/test/jacocoTestReport.xml
|
||||
org.gradle.jvmargs=-Xmx4096M
|
||||
containerAlwaysOn=false
|
||||
disableLint=false
|
||||
disableLint=false
|
||||
projectName=postgres-json
|
||||
@@ -36,5 +36,10 @@ sealed class Returns(
|
||||
isSetOf: Boolean,
|
||||
) : Returns("any", isSetOf)
|
||||
|
||||
class Unknown(
|
||||
definition: String,
|
||||
isSetOf: Boolean,
|
||||
) : Returns(definition, isSetOf)
|
||||
|
||||
class Void : Returns("void", false)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import fr.postgresjson.definition.Parameter.Direction.OUT
|
||||
import fr.postgresjson.definition.ParameterType
|
||||
import fr.postgresjson.definition.Resource.ParseException
|
||||
import fr.postgresjson.definition.Returns
|
||||
import fr.postgresjson.definition.Returns.Primitive
|
||||
import fr.postgresjson.definition.Returns.Unknown
|
||||
import fr.postgresjson.definition.Returns.Void
|
||||
import java.nio.file.Path
|
||||
import kotlin.text.RegexOption.IGNORE_CASE
|
||||
@@ -34,6 +36,7 @@ internal fun ScriptPart.getFunctionName(): NextScript<String> {
|
||||
throw FunctionNameMalformed(this, e)
|
||||
}
|
||||
}
|
||||
|
||||
internal class FunctionNameMalformed(val script: ScriptPart, cause: Throwable? = null) :
|
||||
ParseException("Function name is malformed", cause)
|
||||
|
||||
@@ -78,6 +81,7 @@ private fun ScriptPart.toParameter(): Parameter {
|
||||
default = script.getParameterDefault().trimSpace().apply { script = nextScriptPart }.value,
|
||||
)
|
||||
}
|
||||
|
||||
private fun ScriptPart.getParameterMode(): NextScript<Direction> {
|
||||
return when {
|
||||
restOfScript.startsWith("inout ", true) -> NextScript(INOUT, restOfScript.drop("inout ".length))
|
||||
@@ -95,6 +99,7 @@ private fun ScriptPart.getParameterName(): NextScript<String> {
|
||||
throw ParameterNameMalformed(this, e)
|
||||
}
|
||||
}
|
||||
|
||||
private class ParameterNameMalformed(val script: ScriptPart, cause: Throwable) :
|
||||
ParseException("Parameter name is malformed", cause)
|
||||
|
||||
@@ -153,8 +158,52 @@ private class ParameterDefaultMalformed(val script: ScriptPart) :
|
||||
* TODO Finalize this
|
||||
*/
|
||||
internal fun ScriptPart.getReturns(): NextScript<Returns> {
|
||||
return NextScript(Void(), "")
|
||||
val rest = this.trimSpace()
|
||||
if (!rest.restOfScript.startsWith("returns")) {
|
||||
return NextScript(Void(), "")
|
||||
}
|
||||
var returns = ScriptPart(rest.restOfScript.drop("returns".length))
|
||||
.getNextScript { this.afterBeginBy(Regex("\\s+language\\s+", IGNORE_CASE), Regex("\\s+as\\s+", IGNORE_CASE)) }
|
||||
.trimSpace()
|
||||
.value
|
||||
.trimStart()
|
||||
|
||||
val isSetOf = returns.startsWith("SETOF", ignoreCase = true)
|
||||
|
||||
if (isSetOf) {
|
||||
returns = returns.drop("SETOF".length).trimStart()
|
||||
}
|
||||
|
||||
val returnsClass = if (returns.isBlank()) {
|
||||
Void()
|
||||
} else if (primitiveList.contains(ScriptPart(returns).getParameterType().value.name)) {
|
||||
Primitive(returns, isSetOf)
|
||||
} else {
|
||||
Unknown(returns, isSetOf)
|
||||
}
|
||||
|
||||
return NextScript(returnsClass, "")
|
||||
}
|
||||
|
||||
private val primitiveList = listOf(
|
||||
"text",
|
||||
"varchar",
|
||||
"character varying",
|
||||
"character",
|
||||
"char",
|
||||
"int",
|
||||
"smallint",
|
||||
"integer",
|
||||
"bigint",
|
||||
"decimal",
|
||||
"real",
|
||||
"double precision",
|
||||
"float",
|
||||
"numeric",
|
||||
"boolean",
|
||||
"json",
|
||||
"jsonb",
|
||||
)
|
||||
|
||||
class ParseError(message: String? = null, cause: Throwable? = null) :
|
||||
ParseException(message ?: "Parsing fail", cause)
|
||||
|
||||
@@ -156,7 +156,10 @@ internal data class Context(
|
||||
val script: String,
|
||||
) {
|
||||
fun afterBeginBy(vararg texts: String): Boolean = texts.any {
|
||||
script.substring(index + 1).take(it.length) == it
|
||||
script.drop(index + 1).take(it.length) == it
|
||||
}
|
||||
fun afterBeginBy(vararg texts: Regex): Boolean = texts.any {
|
||||
it.matchAt(script, index + 1) != null
|
||||
}
|
||||
|
||||
val nextChar: Char? get() = script.substring(index + 1).getOrNull(0)
|
||||
|
||||
@@ -9,16 +9,16 @@ import fr.postgresjson.serializer.toTypeReference
|
||||
import io.kotest.core.spec.style.StringSpec
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
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 kotlin.reflect.full.hasAnnotation
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNotNull
|
||||
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()
|
||||
|
||||
@SqlSerializable
|
||||
@@ -116,7 +116,7 @@ class ConnectionTest: StringSpec({
|
||||
"test call request without args" {
|
||||
val result: ObjTest? = connection.execute(
|
||||
"select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', 'myName')",
|
||||
object: TypeReference<ObjTest>() {}
|
||||
object : TypeReference<ObjTest>() {}
|
||||
) {
|
||||
assertEquals("myName", this.deserialize<ObjTest>()?.name)
|
||||
}
|
||||
@@ -125,7 +125,7 @@ class ConnectionTest: StringSpec({
|
||||
}
|
||||
|
||||
"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()
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ class ConnectionTest: StringSpec({
|
||||
)
|
||||
|
||||
assertThrows<DataNotFoundException> {
|
||||
execute("select * from test where false;", object: TypeReference<ObjTest>() {})
|
||||
execute("select * from test where false;", object : TypeReference<ObjTest>() {})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package fr.postgresjson.definition
|
||||
|
||||
import fr.postgresjson.definition.Returns.Primitive
|
||||
import fr.postgresjson.definition.parse.parseFunction
|
||||
import io.kotest.core.spec.style.FreeSpec
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.amshove.kluent.shouldBeInstanceOf
|
||||
|
||||
class FunctionTest: FreeSpec({
|
||||
class FunctionTest : FreeSpec({
|
||||
"Function name" - {
|
||||
"all in lower" {
|
||||
parseFunction(
|
||||
@@ -83,7 +85,6 @@ class FunctionTest: FreeSpec({
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
"Parameters" - {
|
||||
"One parameter text" - {
|
||||
val param = parseFunction(
|
||||
@@ -215,6 +216,50 @@ class FunctionTest: FreeSpec({
|
||||
}
|
||||
}
|
||||
|
||||
"Function Returns" - {
|
||||
"should return the type text" {
|
||||
val returns = parseFunction(
|
||||
// language=PostgreSQL
|
||||
"""
|
||||
create or replace function myfun() returns text language plpgsql as
|
||||
$$ begin; end$$;
|
||||
""".trimIndent()
|
||||
).returns
|
||||
|
||||
returns shouldBeInstanceOf Primitive::class
|
||||
returns.definition shouldBe "text"
|
||||
returns.isSetOf shouldBe false
|
||||
}
|
||||
|
||||
"should return the type character varying" {
|
||||
val returns = parseFunction(
|
||||
// language=PostgreSQL
|
||||
"""
|
||||
create or replace function myfun() returns character varying language plpgsql as
|
||||
$$ begin; end$$;
|
||||
""".trimIndent()
|
||||
).returns
|
||||
|
||||
returns shouldBeInstanceOf Primitive::class
|
||||
returns.definition shouldBe "character varying"
|
||||
returns.isSetOf shouldBe false
|
||||
}
|
||||
|
||||
"should return the type character varying(255)" {
|
||||
val returns = parseFunction(
|
||||
// language=PostgreSQL
|
||||
"""
|
||||
create or replace function myfun() returns character varying(255) language plpgsql as
|
||||
$$ begin; end$$;
|
||||
""".trimIndent()
|
||||
).returns
|
||||
|
||||
returns shouldBeInstanceOf Primitive::class
|
||||
returns.definition shouldBe "character varying(255)"
|
||||
returns.isSetOf shouldBe false
|
||||
}
|
||||
}
|
||||
|
||||
// "function returns" - {
|
||||
// "should return the type text if function return text" {
|
||||
// Function(
|
||||
|
||||
Reference in New Issue
Block a user