fix caps in quoted names

This commit is contained in:
2023-06-03 00:19:10 +02:00
parent f4e88d385b
commit 3e3a72306b
3 changed files with 37 additions and 7 deletions

View File

@@ -32,6 +32,7 @@ internal fun parseFunction(script: String, source: Path? = null): Function {
internal fun ScriptPart.getFunctionName(): NextScript<String> {
try {
return getNextScript { status.isNotEscaped() && afterBeginBy("(", " ", "\n") }
.changeValue { unescapeOrLowercase() }
} catch (e: ParseException) {
throw FunctionNameMalformed(this, e)
}
@@ -95,6 +96,7 @@ private fun ScriptPart.getParameterMode(): NextScript<Direction> {
private fun ScriptPart.getParameterName(): NextScript<String> {
try {
return getNextScript { afterBeginBy(" ", "\n") && status.isNotEscaped() }
.changeValue { unescapeOrLowercase() }
} catch (e: ParseException) {
throw ParameterNameMalformed(this, e)
}

View File

@@ -61,7 +61,7 @@ internal fun ScriptPart.getNextScript(isEnd: Context.() -> Boolean = { false }):
if (isEnd(Context(index, c, status.copy(), restOfScript))) {
return NextScript(
restOfScript.take(index + 1).unescape(),
restOfScript.take(index + 1),
restOfScript.drop(index + 1),
)
}
@@ -77,13 +77,19 @@ internal fun ScriptPart.getNextScript(isEnd: Context.() -> Boolean = { false }):
throw ParseError()
}
private fun String.unescape(): String {
internal fun ScriptPart.unescapeOrLowercase(): ScriptPart = restOfScript
.run(String::unescapeOrLowercase)
.let(::ScriptPart)
internal fun String.unescapeOrLowercase(): String {
val first = take(1)
val last = takeLast(1)
return if (first == last && first in listOf("\"", "'")) {
return if (first == last && first == "'") {
drop(1).dropLast(1).replace("$first$first", first).lowercase()
} else if (first == last && first == "\"") {
drop(1).dropLast(1).replace("$first$first", first)
} else {
this
this.lowercase()
}
}
@@ -142,6 +148,14 @@ internal inline fun ScriptPart.change(block: String.() -> String): ScriptPart {
return ScriptPart(restOfScript.run(block))
}
@OptIn(ExperimentalContracts::class)
internal inline fun <T> NextScript<T>.changeValue(block: T.() -> T): NextScript<T> {
contract {
callsInPlace(block, EXACTLY_ONCE)
}
return NextScript(value.run(block), nextScriptPart.restOfScript)
}
internal fun ScriptPart.getNextInteger(): NextScript<Int?> {
val digits = restOfScript.takeWhile { it.isDigit() }
val restOfScript = restOfScript.trimStart { it.isDigit() }

View File

@@ -24,7 +24,7 @@ class FunctionTest : FreeSpec({
}
}
"first letter caps" {
"first letter caps without quoted" {
parseFunction(
// language=PostgreSQL
"""
@@ -32,7 +32,7 @@ class FunctionTest : FreeSpec({
$$ begin; end$$;
""".trimIndent()
).apply {
name shouldBe "Myfun"
name shouldBe "myfun"
}
}
@@ -60,7 +60,7 @@ class FunctionTest : FreeSpec({
}
}
"escaped name with double quote in name" {
"quoted name with double quote in name" {
parseFunction(
// language=PostgreSQL
"""
@@ -153,6 +153,20 @@ class FunctionTest : FreeSpec({
param[1].name shouldBe "#@€"
}
}
"Parameters with Caps" - {
val param = parseFunction(
// language=PostgreSQL
"""
create or replace function myfun("One" text, Two text) returns text language plpgsql as
$$ begin end;$$;
""".trimIndent()
).parameters
"should have first parameter name" {
param[0].name shouldBe "One"
param[1].name shouldBe "two"
}
}
"Parameters with type `character varying(255)`" - {
val param = parseFunction(