apply "replaceNamedArgByQuestionMark" on exec() function
This commit is contained in:
@@ -172,7 +172,7 @@ class Connection(
|
|||||||
override fun exec(sql: String, values: List<Any?>): QueryResult {
|
override fun exec(sql: String, values: List<Any?>): QueryResult {
|
||||||
val compiledValues = compileArgs(values)
|
val compiledValues = compileArgs(values)
|
||||||
return stopwatchQuery(sql, compiledValues) {
|
return stopwatchQuery(sql, compiledValues) {
|
||||||
connect().sendPreparedStatement(sql, compiledValues).join()
|
connect().sendPreparedStatement(replaceNamedArgByQuestionMark(sql), compiledValues).join()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,37 +215,41 @@ class Connection(
|
|||||||
|
|
||||||
private fun <T> replaceArgs(sql: String, values: Map<String, Any?>, block: ParametersQuery.() -> T): T {
|
private fun <T> replaceArgs(sql: String, values: Map<String, Any?>, block: ParametersQuery.() -> T): T {
|
||||||
val paramRegex = "(?<!:):([a-zA-Z0-9_-]+)".toRegex(RegexOption.IGNORE_CASE)
|
val paramRegex = "(?<!:):([a-zA-Z0-9_-]+)".toRegex(RegexOption.IGNORE_CASE)
|
||||||
val newArgs = paramRegex.findAll(sql).map { match ->
|
val orderedArgs = paramRegex.findAll(sql).map { match ->
|
||||||
val name = match.groups[1]!!.value
|
val name = match.groups[1]!!.value
|
||||||
values[name] ?: values[name.trimStart('_')] ?: queryError("""Parameter "$name" missing""", sql, values)
|
values[name] ?: values[name.trimStart('_')] ?: queryError("""Parameter "$name" missing""", sql, values)
|
||||||
}.toList()
|
}.toList()
|
||||||
|
|
||||||
var newSql = sql
|
return block(ParametersQuery(replaceNamedArgByQuestionMark(sql), orderedArgs))
|
||||||
values.forEach { (key, _) ->
|
|
||||||
val regex = ":_?$key".toRegex()
|
|
||||||
newSql = newSql.replace(regex, "?")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return block(ParametersQuery(newSql, newArgs))
|
private fun replaceNamedArgByQuestionMark(sql: String): String =
|
||||||
|
"(?<!:):([a-zA-Z0-9_-]+)"
|
||||||
|
.toRegex(RegexOption.IGNORE_CASE)
|
||||||
|
.replace(sql, "?")
|
||||||
|
|
||||||
|
private fun insertArgsValuesIntoSql(sql: String, values: List<Any?>): String {
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
/* The regular expression matches a question mark "?" alone, not preceded or followed by another question mark */
|
||||||
|
return """(?<!\?)(\?)(?!\?)"""
|
||||||
|
.toRegex(RegexOption.IGNORE_CASE)
|
||||||
|
.replace(sql) {
|
||||||
|
values[i]
|
||||||
|
?.toString()
|
||||||
|
?.also { ++i }
|
||||||
|
?.let(this::escapeParameter)
|
||||||
|
?: queryError("Parameter $i missing", sql, values)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> replaceArgsIntoSql(sql: String, values: List<Any?>, block: (String) -> T): T {
|
private fun <T> replaceArgsIntoSql(sql: String, values: List<Any?>, block: (String) -> T): T {
|
||||||
/* The regular expression matches a question mark "?" alone, not preceded or followed by another question mark */
|
return if (values.isNotEmpty()) {
|
||||||
val paramRegex = """(?<!\?)(\?)(?!\?)""".toRegex(RegexOption.IGNORE_CASE)
|
sql
|
||||||
var i = 0
|
.let(this::replaceNamedArgByQuestionMark)
|
||||||
if (values.isNotEmpty()) {
|
.let { insertArgsValuesIntoSql(it, values) }
|
||||||
/* for each question mark, replace by the value */
|
.let(block)
|
||||||
val newSql = paramRegex.replace(sql) {
|
} else block(sql)
|
||||||
values[i] ?: queryError("Parameter $i missing", sql, values)
|
|
||||||
val valToReplace = values[i].toString()
|
|
||||||
++i
|
|
||||||
escapeParameter(valToReplace)
|
|
||||||
}
|
|
||||||
|
|
||||||
return block(newSql)
|
|
||||||
}
|
|
||||||
|
|
||||||
return block(sql)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import fr.postgresjson.connexion.select
|
|||||||
import fr.postgresjson.connexion.selectOne
|
import fr.postgresjson.connexion.selectOne
|
||||||
import fr.postgresjson.connexion.update
|
import fr.postgresjson.connexion.update
|
||||||
import fr.postgresjson.entity.UuidEntity
|
import fr.postgresjson.entity.UuidEntity
|
||||||
|
import fr.postgresjson.serializer.deserialize
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertThrows
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
@@ -150,6 +151,16 @@ class RequesterTest : TestAbstract() {
|
|||||||
assertEquals(1, result.rowsAffected)
|
assertEquals(1, result.rowsAffected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `call exec on query with a list of arguments`() {
|
||||||
|
val resources = this::class.java.getResource("/sql/query")?.toURI()
|
||||||
|
val result = Requester(connection, queriesDirectory = resources)
|
||||||
|
.getQuery("selectOneWithParameters")
|
||||||
|
.exec(listOf("myName"))
|
||||||
|
|
||||||
|
assertEquals("myName", result.rows[0].getString(0)?.deserialize<ObjTest>()?.name)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call exec on function`() {
|
fun `call exec on function`() {
|
||||||
val resources = this::class.java.getResource("/sql/function/Test")?.toURI()
|
val resources = this::class.java.getResource("/sql/function/Test")?.toURI()
|
||||||
@@ -181,6 +192,17 @@ class RequesterTest : TestAbstract() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `call sendQuery with same name of arguments as list`() {
|
||||||
|
val resources = this::class.java.getResource("/sql/query")?.toURI()
|
||||||
|
Requester(connection, queriesDirectory = resources)
|
||||||
|
.getQuery("selectMultipleWithSameArgs")
|
||||||
|
.sendQuery(listOf("myName", "myName2")).run {
|
||||||
|
assertEquals("myName", rows[0].getString("firstName"))
|
||||||
|
assertEquals("myName2", rows[0].getString("secondName"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `call sendQuery with arguments on not same orders`() {
|
fun `call sendQuery with arguments on not same orders`() {
|
||||||
val resources = this::class.java.getResource("/sql/query")?.toURI()
|
val resources = this::class.java.getResource("/sql/query")?.toURI()
|
||||||
|
|||||||
Reference in New Issue
Block a user