WIP: Compiled SQL function #33

Draft
flecomte wants to merge 37 commits from compiled_sql_function into master
2 changed files with 58 additions and 32 deletions
Showing only changes of commit eac77d7419 - Show all commits

View File

@@ -81,7 +81,7 @@ class Function(
try {
return getNextScript { status.isNotEscaped() && listOf("(", " ", "\n").any { afterBeginBy(it) } }
} catch (e: NameMalformed) {
throw FunctionNameMalformed()
throw FunctionNameMalformed(null, e)
}
}
@@ -93,37 +93,6 @@ class Function(
return ScriptPart(restOfScript.run(block))
}
/**
* Get a name.
* You can define a list of characters that end the name. Like `(` or space.
*/
private fun ScriptPart.getAbstractName(endString: String, includeEnd: Boolean = false): NextScript<String> =
getAbstractName(listOf(endString), includeEnd)
/**
* Get a name.
* You can define a list of characters that end the name. Like `(` or space.
*/
@Deprecated("replace by getNextScript", ReplaceWith("getNextScript"))
private fun ScriptPart.getAbstractName(endStrings: List<String>, includeEnd: Boolean = false): NextScript<String> {
var nameIsEscaped = false
for ((i, c) in restOfScript.withIndex()) {
val isEndOfString = endStrings.filter { restOfScript.substring(i).take(it.length) == it }.length > 0
if (c == '"' && i == 0) {
nameIsEscaped = true
} else if (c == '"' && i > 0 && (restOfScript[i + 1] == '"' || restOfScript[i - 1] == '"')) {
continue
} else if (c == '"' && i > 0 && !nameIsEscaped) {
throw NameMalformed()
} else if ((c == '"' && i > 0 && nameIsEscaped) || (!nameIsEscaped && isEndOfString)) {
val dropCount = i + if (includeEnd) 1 else 0
return NextScript(restOfScript.take(i).trim('"').replace("\"\"", "\""), restOfScript.drop(dropCount))
}
}
throw NameMalformed()
}
data class Status(
var doubleQuoted: Boolean = false, // "
var simpleQuoted: Boolean = false, // '

View File

@@ -129,6 +129,63 @@ class FunctionTest: FreeSpec({
param[1].type.name shouldBe "int"
}
}
"parameters with `character varying(255)`" - {
val param = Function(
// language=PostgreSQL
"""
create or replace function myfun(one character varying(255)) returns text language plpgsql as
$$ begin end;$$;
""".trimIndent()
).parameters
"should have 1 parameters" {
param shouldHaveSize 1
}
"should have name" {
param[0].name shouldBe "one"
}
"should have type name" {
param[0].type.name shouldBe "character varying"
}
"should have type precision" {
param[0].type.precision shouldBe 255
param[0].type.scale shouldBe null
}
}
"parameters with `numeric(16, 8)`" - {
val param = Function(
// language=PostgreSQL
"""
create or replace function myfun(one numeric(16, 8)) returns text language plpgsql as
$$ begin end;$$;
""".trimIndent()
).parameters
"should have 1 parameters" {
param shouldHaveSize 1
}
"should have name" {
param[0].name shouldBe "one"
}
"should have type name" {
param[0].type.name shouldBe "numeric"
}
"should have type precision" {
param[0].type.precision shouldBe 16
}
"should have type scale" {
param[0].type.scale shouldBe 8
}
}
}
// "function returns" - {