Add more tests

remove "sendQuery" on function
sendQuery now return QueryResult
remove null on queryError message
This commit is contained in:
2021-07-18 01:19:27 +02:00
parent 35d43abc4b
commit a4a4ef5f6f
10 changed files with 116 additions and 78 deletions

View File

@@ -185,11 +185,11 @@ class Connection(
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
override fun sendQuery(sql: String, values: List<Any?>): Int { override fun sendQuery(sql: String, values: List<Any?>): QueryResult {
val compiledValues = compileArgs(values) val compiledValues = compileArgs(values)
return stopwatchQuery(sql, compiledValues) { return stopwatchQuery(sql, compiledValues) {
replaceArgsIntoSql(sql, compiledValues) { replaceArgsIntoSql(sql, compiledValues) {
connect().sendQuery(it).join().rowsAffected.toInt() connect().sendQuery(it).join()
} }
} }
} }
@@ -197,7 +197,7 @@ class Connection(
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
override fun sendQuery(sql: String, values: Map<String, Any?>): Int { override fun sendQuery(sql: String, values: Map<String, Any?>): QueryResult {
return replaceArgs(sql, values) { return replaceArgs(sql, values) {
sendQuery(this.sql, this.parameters) sendQuery(this.sql, this.parameters)
} }
@@ -217,7 +217,7 @@ class Connection(
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 newArgs = 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 var newSql = sql
@@ -296,11 +296,11 @@ class Connection(
""" """
|$msg |$msg
| |
|${parameters.joinToString(", ") { it.toString() }.prependIndent(" > ")} |${parameters.joinToString(", ") { it.toString() }.prependIndent(" > ") ?: ""}
|${sql.prependIndent(" > ")} |${sql.prependIndent(" > ")}
|${result?.let { "-----" }?.prependIndent(" > ")} |${result?.let { "-----" }?.prependIndent(" > ") ?: ""}
|${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ")} |${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ") ?: ""}
|${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ")} |${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ") ?: ""}
""".trimMargin().trim(' ', '\n') """.trimMargin().trim(' ', '\n')
) )
@@ -313,11 +313,11 @@ class Connection(
""" """
|$msg |$msg
| |
|${parameters.map { it.key + ": " + it.value }.joinToString(", ").prependIndent(" > ")} |${parameters.map { ":" + it.key + " = " + it.value }.joinToString(", ").prependIndent(" > ") ?: ""}
|${sql.prependIndent(" > ")} |${sql.prependIndent(" > ")}
|${result?.let { "-----" }?.prependIndent(" > ")} |${result?.let { "-----" }?.prependIndent(" > ") ?: ""}
|${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ")} |${result?.columnNames()?.joinToString(" | ")?.prependIndent(" > ") ?: ""}
|${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ")} |${result?.map { it.joinToString(" | ") }?.joinToString("\n")?.prependIndent(" > ") ?: ""}
""".trimMargin().trim(' ') """.trimMargin().trim(' ', '\n')
) )
} }

View File

@@ -111,17 +111,4 @@ sealed interface EmbedExecutable {
fun perform(values: List<Any?>) { exec(values) } fun perform(values: List<Any?>) { exec(values) }
fun perform(values: Map<String, Any?>) { exec(values) } fun perform(values: Map<String, Any?>) { exec(values) }
fun perform(vararg values: Pair<String, Any?>) = perform(values.toMap()) fun perform(vararg values: Pair<String, Any?>) = perform(values.toMap())
/**
* Warning: this method not use prepared statement
*/
fun sendQuery(values: List<Any?>): Int
/**
* Warning: this method not use prepared statement
*/
fun sendQuery(values: Map<String, Any?>): Int
/**
* Warning: this method not use prepared statement
*/
fun sendQuery(vararg values: Pair<String, Any?>): Int = sendQuery(values.toMap())
} }

View File

@@ -125,17 +125,17 @@ interface Executable {
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
fun <R : EntityI> sendQuery(sql: String, value: R): Int = sendQuery(sql, listOf(value)) fun <R : EntityI> sendQuery(sql: String, value: R): QueryResult = sendQuery(sql, listOf(value))
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
fun sendQuery(sql: String, values: List<Any?> = emptyList()): Int fun sendQuery(sql: String, values: List<Any?>): QueryResult
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
fun sendQuery(sql: String, values: Map<String, Any?>): Int fun sendQuery(sql: String, values: Map<String, Any?>): QueryResult
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
fun sendQuery(sql: String, vararg values: Pair<String, Any?>): Int = sendQuery(sql, values.toMap()) fun sendQuery(sql: String, vararg values: Pair<String, Any?>): QueryResult = sendQuery(sql, values.toMap())
} }

View File

@@ -82,22 +82,6 @@ class Function(val definition: Function, override val connection: Connection) :
override fun exec(values: Map<String, Any?>): QueryResult = connection.exec(compileSql(values), values) override fun exec(values: Map<String, Any?>): QueryResult = connection.exec(compileSql(values), values)
/**
* Warning: this method not use prepared statement
*/
override fun sendQuery(values: List<Any?>): Int {
exec(values)
return 0
}
/**
* Warning: this method not use prepared statement
*/
override fun sendQuery(values: Map<String, Any?>): Int {
exec(values)
return 0
}
private fun <R : EntityI> compileArgs(value: R): String = compileArgs(listOf(value)) private fun <R : EntityI> compileArgs(value: R): String = compileArgs(listOf(value))
private fun compileArgs(values: List<Any?>): String { private fun compileArgs(values: List<Any?>): String {

View File

@@ -76,10 +76,14 @@ class Query(override val name: String, private val sql: String, override val con
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
override fun sendQuery(values: List<Any?>): Int = connection.sendQuery(sql, values) fun sendQuery(values: List<Any?>): QueryResult = connection.sendQuery(sql, values)
/** /**
* Warning: this method not use prepared statement * Warning: this method not use prepared statement
*/ */
override fun sendQuery(values: Map<String, Any?>): Int = connection.sendQuery(sql, values) fun sendQuery(values: Map<String, Any?>): QueryResult = connection.sendQuery(sql, values)
/**
* Warning: this method not use prepared statement
*/
fun sendQuery(vararg values: Pair<String, Any?>): QueryResult = sendQuery(values.toMap())
} }

View File

@@ -47,21 +47,25 @@ data class Function(
} }
} }
this::class.java.classLoader.getResource("sql/migration/insertFunction.sql")!!.readText().let { this::class.java.classLoader
connection.selectOne<MigrationEntity>(it, listOf(up.name, up.getDefinition(), up.script, down.script))?.let { function -> .getResource("sql/migration/insertFunction.sql")!!.readText()
.let { connection.selectOne<MigrationEntity>(it, listOf(up.name, up.getDefinition(), up.script, down.script)) }
?.let { function ->
executedAt = function.executedAt executedAt = function.executedAt
doExecute = Action.OK doExecute = Action.OK
} }
}
return Status.OK return Status.OK
} }
override fun down(): Status { override fun down(): Status {
connection.sendQuery(down.script) connection.sendQuery(down.script)
this::class.java.classLoader.getResource("sql/migration/deleteFunction.sql")!!.readText().let { this::class.java.classLoader
connection.sendQuery(it, listOf(down.name)) .getResource("sql/migration/deleteFunction.sql")!!
} .readText()
.let { connection.sendQuery(it, listOf(down.name)) }
return Status.OK return Status.OK
} }
@@ -75,13 +79,9 @@ data class Function(
return Status.OK return Status.OK
} }
fun copy(): Function { fun copy(): Function = this
return this.copy(up = up, down = down, connection = connection, executedAt = executedAt).also { .copy(up = up, down = down, connection = connection, executedAt = executedAt)
it.doExecute = this.doExecute .also { it.doExecute = this.doExecute }
}
}
infix fun `is different from`(other: DefinitionFunction): Boolean { infix fun `is different from`(other: DefinitionFunction): Boolean = other.script != this.up.script
return other.script != this.up.script
}
} }

View File

@@ -236,16 +236,16 @@ class ConnectionTest : TestAbstract() {
assertEquals( assertEquals(
""" """
|The query not return the "total" column The query not return the "total" column
|
| > offset: 0, limit: 2 > :offset = 0, :limit = 2
| > SELECT null > SELECT null
| > LIMIT :limit > LIMIT :limit
| > OFFSET :offset > OFFSET :offset
| > ----- > -----
| > ?column? > ?column?
| > null > null
""".trimMargin(), """.trimIndent(),
exception.message exception.message
) )
} }

View File

@@ -1,5 +1,6 @@
package fr.postgresjson package fr.postgresjson
import fr.postgresjson.connexion.Connection.QueryError
import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Paginated
import fr.postgresjson.connexion.Requester import fr.postgresjson.connexion.Requester
import fr.postgresjson.connexion.Requester.NoFunctionDefined import fr.postgresjson.connexion.Requester.NoFunctionDefined
@@ -160,23 +161,83 @@ class RequesterTest : TestAbstract() {
} }
@Test @Test
fun `call sendQuery on query with name`() { fun `call exec on query with name`() {
val resources = this::class.java.getResource("/sql/query")?.toURI() val resources = this::class.java.getResource("/sql/query")?.toURI()
val result = Requester(connection, queriesDirectory = resources) val result = Requester(connection, queriesDirectory = resources)
.getQuery("DeleteTest") .getQuery("DeleteTest")
.sendQuery() .exec()
assertEquals(0, result) assertEquals(0, result.rowsAffected)
} }
@Test @Test
fun `call sendQuery on function`() { fun `call sendQuery with same name of arguments`() {
val resources = this::class.java.getResource("/sql/query")?.toURI()
Requester(connection, queriesDirectory = resources)
.getQuery("selectMultipleWithSameArgs")
.sendQuery("name" to "myName").run {
assertEquals("myName", rows[0].getString("firstName"))
assertEquals("myName", rows[0].getString("secondName"))
}
}
@Test
fun `call sendQuery with arguments on not same orders`() {
val resources = this::class.java.getResource("/sql/query")?.toURI()
Requester(connection, queriesDirectory = resources)
.getQuery("selectMultipleDifferentArgs")
.sendQuery("first" to "firstName", "second" to "secondName").run {
assertEquals("firstName", rows[0].getString("firstName"))
assertEquals("secondName", rows[0].getString("secondName"))
}
Requester(connection, queriesDirectory = resources)
.getQuery("selectMultipleDifferentArgs")
.sendQuery("second" to "secondName", "first" to "firstName").run {
assertEquals("firstName", rows[0].getString("firstName"))
assertEquals("secondName", rows[0].getString("secondName"))
}
Requester(connection, queriesDirectory = resources)
.getQuery("selectMultipleDifferentArgs")
.sendQuery("second" to "secondName", "first" to "firstName").run {
assertEquals("firstName", rows[0].getString(0))
assertEquals("secondName", rows[0].getString(1))
}
}
@Test
fun `call sendQuery with wrong number of arguments`() {
val resources = this::class.java.getResource("/sql/query")?.toURI()
assertThrows(QueryError::class.java) {
Requester(connection, queriesDirectory = resources)
.getQuery("selectMultipleDifferentArgs")
.sendQuery("first" to "firstName").run {
assertEquals("firstName", rows[0].getString(0))
assertEquals("secondName", rows[0].getString(1))
}
}.let {
assertEquals(
"""
Parameter "second" missing
> :first = firstName
> SELECT :first::text as "firstName", :second::text as "secondName";
""".trimIndent(),
it.message
)
}
}
@Test
fun `call exec on function with pair as arguments`() {
val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val resources = this::class.java.getResource("/sql/function/Test")?.toURI()
val result = Requester(connection, functionsDirectory = resources) val result = Requester(connection, functionsDirectory = resources)
.getFunction("function_void") .getFunction("function_void")
.sendQuery(listOf("test")) .exec("name" to "test")
assertEquals(0, result) assertEquals(1, result.rowsAffected)
} }
@Test @Test

View File

@@ -0,0 +1 @@
SELECT :first::text as "firstName", :second::text as "secondName";

View File

@@ -0,0 +1 @@
SELECT :name::text as "firstName", :name::text as "secondName";