WIP: Compiled SQL function #33
@@ -106,7 +106,7 @@ private class ParameterNameMalformed(val script: ScriptPart, cause: Throwable) :
|
|||||||
@Throws(ParameterTypeMalformed::class)
|
@Throws(ParameterTypeMalformed::class)
|
||||||
private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
||||||
val fullType = try {
|
val fullType = try {
|
||||||
val endTextList = arrayOf(" default ", "=", ")")
|
val endTextList = arrayOf(" default ", "=")
|
||||||
getNextScript { afterBeginBy(texts = endTextList) }
|
getNextScript { afterBeginBy(texts = endTextList) }
|
||||||
} catch (e: ParseError) {
|
} catch (e: ParseError) {
|
||||||
throw ParameterTypeMalformed(this, e)
|
throw ParameterTypeMalformed(this, e)
|
||||||
@@ -115,20 +115,26 @@ private fun ScriptPart.getParameterType(): NextScript<ParameterType> {
|
|||||||
var rest: ScriptPart = fullType.valueAsScriptPart()
|
var rest: ScriptPart = fullType.valueAsScriptPart()
|
||||||
|
|
||||||
val name = rest
|
val name = rest
|
||||||
.getNextScript { afterBeginBy("(") }
|
.getNextScript { afterBeginBy("(", "[") }
|
||||||
.apply { rest = nextScriptPart }
|
.apply { rest = nextScriptPart }
|
||||||
|
rest = rest.trimStart(' ', '\n', '\t', ',', '(')
|
||||||
val precision = rest
|
val precision = rest
|
||||||
.getNextInteger()
|
.getNextInteger()
|
||||||
.apply { rest = nextScriptPart }
|
.apply { rest = nextScriptPart }
|
||||||
|
rest = rest.trimStart(' ', '\n', '\t', ',')
|
||||||
val scale = rest
|
val scale = rest
|
||||||
.getNextInteger()
|
.getNextInteger()
|
||||||
.apply { rest = nextScriptPart }
|
.apply { rest = nextScriptPart }
|
||||||
|
rest = rest.trimStart(' ', '\n', '\t', ')')
|
||||||
|
|
||||||
|
val isArray = rest.restOfScript.contains("[]")
|
||||||
|
|
||||||
return NextScript(
|
return NextScript(
|
||||||
ParameterType(
|
ParameterType(
|
||||||
name = name.value.trim(),
|
name = name.value.trim().trim('[', ']'),
|
||||||
precision = precision.value,
|
precision = precision.value,
|
||||||
scale = scale.value
|
scale = scale.value,
|
||||||
|
isArray = isArray
|
||||||
),
|
),
|
||||||
fullType.nextScriptPart.restOfScript
|
fullType.nextScriptPart.restOfScript
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -60,12 +60,20 @@ internal fun ScriptPart.getNextScript(isEnd: Context.() -> Boolean = { false }):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isEnd(Context(index, c, status.copy(), restOfScript))) {
|
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()) {
|
if (status.isNotEscaped()) {
|
||||||
return NextScript(restOfScript.trim(), "").trimSpace()
|
return NextScript(
|
||||||
|
restOfScript.trim(),
|
||||||
|
"",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ParseError()
|
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 } })
|
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 {
|
internal fun ScriptPart.trimEnd(vararg chars: Char): ScriptPart {
|
||||||
return this.change { dropLastWhile { it in chars } }
|
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?> {
|
internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
|
||||||
val trimmed = restOfScript.trimStart { !it.isDigit() }
|
val digits = restOfScript.takeWhile { it.isDigit() }
|
||||||
val digits = trimmed.takeWhile { it.isDigit() }
|
val restOfScript = restOfScript.trimStart { it.isDigit() }
|
||||||
val restOfScript = trimmed.trimStart { it.isDigit() }
|
|
||||||
return NextScript(digits.toIntOrNull(), restOfScript).trimSpace()
|
return NextScript(digits.toIntOrNull(), restOfScript).trimSpace()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -309,6 +309,78 @@ class FunctionTest : FreeSpec({
|
|||||||
param[3].direction shouldBe IN
|
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" - {
|
"Function Returns" - {
|
||||||
|
|||||||
Reference in New Issue
Block a user