WIP: Compiled SQL function #33
@@ -106,7 +106,7 @@ private class ParameterNameMalformed(val script: ScriptPart, cause: Throwable) :
|
||||
@Throws(ParameterTypeMalformed::class)
|
||||
private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
||||
val fullType = try {
|
||||
val endTextList = arrayOf(" default ", "=", ")")
|
||||
val endTextList = arrayOf(" default ", "=")
|
||||
getNextScript { afterBeginBy(texts = endTextList) }
|
||||
} catch (e: ParseError) {
|
||||
throw ParameterTypeMalformed(this, e)
|
||||
@@ -115,20 +115,26 @@ private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
||||
var rest: ScriptPart = fullType.valueAsScriptPart()
|
||||
|
||||
val name = rest
|
||||
.getNextScript { afterBeginBy("(") }
|
||||
.getNextScript { afterBeginBy("(", "[") }
|
||||
.apply { rest = nextScriptPart }
|
||||
rest = rest.trimStart(' ', '\n', '\t', ',', '(')
|
||||
val precision = rest
|
||||
.getNextInteger()
|
||||
.apply { rest = nextScriptPart }
|
||||
rest = rest.trimStart(' ', '\n', '\t', ',')
|
||||
val scale = rest
|
||||
.getNextInteger()
|
||||
.apply { rest = nextScriptPart }
|
||||
rest = rest.trimStart(' ', '\n', '\t', ')')
|
||||
|
||||
val isArray = rest.restOfScript.contains("[]")
|
||||
|
||||
return NextScript(
|
||||
ParameterType(
|
||||
name = name.value.trim(),
|
||||
name = name.value.trim().trim('[', ']'),
|
||||
precision = precision.value,
|
||||
scale = scale.value
|
||||
scale = scale.value,
|
||||
isArray = isArray
|
||||
),
|
||||
fullType.nextScriptPart.restOfScript
|
||||
)
|
||||
|
||||
@@ -60,12 +60,20 @@ internal fun ScriptPart.getNextScript(isEnd: Context.() -> Boolean = { false }):
|
||||
}
|
||||
|
||||
if (isEnd(Context(index, c, status.copy(), restOfScript))) {
|
||||
return NextScript(restOfScript.take(index + 1).unescape(), restOfScript.drop(index + 1))
|
||||
return NextScript(
|
||||
restOfScript.take(index + 1).unescape(),
|
||||
restOfScript.drop(index + 1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (status.isNotEscaped()) {
|
||||
return NextScript(restOfScript.trim(), "").trimSpace()
|
||||
return NextScript(
|
||||
restOfScript.trim(),
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
throw ParseError()
|
||||
}
|
||||
|
||||
@@ -99,6 +107,10 @@ internal fun <T> NextScript<T>.trim(vararg chars: Char): NextScript<T> {
|
||||
return NextScript(value, restOfScript.apply { dropWhile { it in chars } })
|
||||
}
|
||||
|
||||
internal fun ScriptPart.trimStart(vararg chars: Char): ScriptPart {
|
||||
return this.change { dropWhile { it in chars } }
|
||||
}
|
||||
|
||||
internal fun ScriptPart.trimEnd(vararg chars: Char): ScriptPart {
|
||||
return this.change { dropLastWhile { it in chars } }
|
||||
}
|
||||
@@ -131,9 +143,8 @@ internal inline fun ScriptPart.change(block: String.() -> String): ScriptPart {
|
||||
}
|
||||
|
||||
internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
|
||||
val trimmed = restOfScript.trimStart { !it.isDigit() }
|
||||
val digits = trimmed.takeWhile { it.isDigit() }
|
||||
val restOfScript = trimmed.trimStart { it.isDigit() }
|
||||
val digits = restOfScript.takeWhile { it.isDigit() }
|
||||
val restOfScript = restOfScript.trimStart { it.isDigit() }
|
||||
return NextScript(digits.toIntOrNull(), restOfScript).trimSpace()
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +309,78 @@ class FunctionTest : FreeSpec({
|
||||
param[3].direction shouldBe IN
|
||||
}
|
||||
}
|
||||
|
||||
"Parameters with type array of numeric" - {
|
||||
val param = parseFunction(
|
||||
// language=PostgreSQL
|
||||
"""
|
||||
create or replace function myfun(one numeric(10, 2)[]) language plpgsql as
|
||||
$$ begin end;$$;
|
||||
""".trimIndent()
|
||||
).parameters
|
||||
|
||||
"should have 1 parameters" {
|
||||
param shouldHaveSize 1
|
||||
}
|
||||
|
||||
"should have parameter name" {
|
||||
param[0].name shouldBe "one"
|
||||
}
|
||||
|
||||
"should have parameter type is array" {
|
||||
param[0].type.isArray shouldBe true
|
||||
}
|
||||
|
||||
"should have parameter type name" {
|
||||
param[0].type.name shouldBe "numeric"
|
||||
}
|
||||
|
||||
"should have parameter type precision" {
|
||||
param[0].type.precision shouldBe 10
|
||||
}
|
||||
|
||||
"should have parameter type scale" {
|
||||
param[0].type.scale shouldBe 2
|
||||
}
|
||||
}
|
||||
|
||||
"Parameters with type array of text" - {
|
||||
val param = parseFunction(
|
||||
// language=PostgreSQL
|
||||
"""
|
||||
create or replace function myfun(one text[], two int[], three text) language plpgsql as
|
||||
$$ begin end;$$;
|
||||
""".trimIndent()
|
||||
).parameters
|
||||
|
||||
"should have 2 parameters" {
|
||||
param shouldHaveSize 3
|
||||
}
|
||||
|
||||
"should have parameter name" {
|
||||
param[0].name shouldBe "one"
|
||||
param[1].name shouldBe "two"
|
||||
param[2].name shouldBe "three"
|
||||
}
|
||||
|
||||
"should have parameter type is array" {
|
||||
param[0].type.isArray shouldBe true
|
||||
param[1].type.isArray shouldBe true
|
||||
param[2].type.isArray shouldBe false
|
||||
}
|
||||
|
||||
"should have parameter type name" {
|
||||
param[0].type.name shouldBe "text"
|
||||
param[1].type.name shouldBe "int"
|
||||
param[2].type.name shouldBe "text"
|
||||
}
|
||||
|
||||
"should have parameter direction" {
|
||||
param[0].direction shouldBe IN
|
||||
param[1].direction shouldBe IN
|
||||
param[2].direction shouldBe IN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Function Returns" - {
|
||||
|
||||
Reference in New Issue
Block a user