diff --git a/docs/usage/multi-level.md b/docs/usage/multi-level.md index 197d867..1360cb8 100644 --- a/docs/usage/multi-level.md +++ b/docs/usage/multi-level.md @@ -62,7 +62,7 @@ import fr.postgresjson.connexion.Requester val requester: Requester = TODO() val result: Parent = requester .getFunction("find_parent_by_id") - .selectOne("id" to "379e0687-9e4a-4781-b0e9-d94a62e4261f") + .execute("id" to "379e0687-9e4a-4781-b0e9-d94a62e4261f") ``` The requester create dynamically this request diff --git a/docs/usage/paginated.md b/docs/usage/paginated.md deleted file mode 100644 index f2df3c2..0000000 --- a/docs/usage/paginated.md +++ /dev/null @@ -1,19 +0,0 @@ -Paginated request -================= - -```kotlin -import fr.postgresjson.connexion.Paginated -import fr.postgresjson.connexion.Requester -import java.util.UUID - -class Article(val id: UUID, val name: String) - -val request: Requester = TODO() -val article: Paginated
= requester - .getFunction("find_articles") - .select( - page = 1, - limit = 10, - "id" to "4a04820e-f880-4d80-b1c9-aeacccb24977" - ) -``` \ No newline at end of file diff --git a/docs/usage/raw-request.md b/docs/usage/raw-request.md index 4c04946..5c1b2f4 100644 --- a/docs/usage/raw-request.md +++ b/docs/usage/raw-request.md @@ -26,10 +26,10 @@ data class Inventor( val id: UUID = UUID.randomUUID(), val name: String, val roles: List = listOf(), -): Serializable +) // Select one entity -val result: Inventor? = connection.selectOne( +val result: Inventor = connection.execute( """ SELECT json_build_object( 'id', '9e65de49-712e-47ce-8bf2-dfffae53a82e', @@ -40,7 +40,7 @@ val result: Inventor? = connection.selectOne( ) // Select multiple entities -val result = connection.select>( +val result = connection.execute>( """ SELECT json_build_array( json_build_object( @@ -60,7 +60,7 @@ val result = connection.select>( ) // Select multiple with real query -val result: List = connection.select( +val result: List = connection.execute( """ select json_agg(i) from inventor i @@ -71,7 +71,7 @@ val result: List = connection.select( // Select multiple with only some rows -val result: List = connection.select( +val result: List = connection.execute( """ select json_agg(i) from ( diff --git a/docs/usage/stored-procedure.md b/docs/usage/stored-procedure.md index 02a567e..f73d7e8 100644 --- a/docs/usage/stored-procedure.md +++ b/docs/usage/stored-procedure.md @@ -22,7 +22,6 @@ val requester = Requester( ```kotlin import java.util.UUID import org.joda.time.DateTime -import fr.postgresjson.entity.Serializable enum class Roles { ROLE_USER, ROLE_ADMIN } @@ -31,15 +30,16 @@ class User( override var username: String, var blockedAt: DateTime? = null, var roles: List = emptyList() -): Serializable +) +@SqlSerializable class UserForCreate( id: UUID = UUID.randomUUID(), username: String, val password: String, blockedAt: DateTime? = null, roles: List = emptyList() -): Serializable +) ``` 3. and, define Repositories [See SQL function](../migrations/migrations.md) @@ -53,19 +53,14 @@ class UserRepository(override var requester: Requester): RepositoryI { fun findById(id: UUID): User { return requester .getFunction("find_user_by_id") // Use the name of the function - .selectOne( - "id" to id // You can pass parameters by their names. The underscore prefix on parameters is not required to be mapped. - ) ?: throw UserNotFound(id) // Throw exception if user not found + .execute("id" to id) // You can pass parameters by their names. The underscore prefix on parameters is not required to be mapped. + // Throw exception if user not found } fun insert(user: UserForCreate): User { return requester .getFunction("insert_user") - .selectOne("resource" to user) - } - - class UserNotFound(override val message: String?, override val cause: Throwable?): Throwable(message, cause) { - constructor(id: UUID): this("No User with ID $id", null) + .execute("resource" to user) } } ``` diff --git a/docs/usage/usage.md b/docs/usage/usage.md index 8064140..06753a8 100644 --- a/docs/usage/usage.md +++ b/docs/usage/usage.md @@ -3,5 +3,4 @@ 1. [Init connection](./init-connection.md) 2. [Raw request](./raw-request.md) 3. [Stored Procedure](./stored-procedure.md) -4. [Paginated request](./paginated.md) -5. [Multi level request](./multi-level.md) \ No newline at end of file +4. [Multi level request](./multi-level.md) \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/connexion/Connection.kt b/src/main/kotlin/fr/postgresjson/connexion/Connection.kt index c5c5a30..6e82597 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Connection.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Connection.kt @@ -3,21 +3,19 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference import com.github.jasync.sql.db.QueryResult import com.github.jasync.sql.db.ResultSet -import com.github.jasync.sql.db.general.ArrayRowData import com.github.jasync.sql.db.pool.ConnectionPool import com.github.jasync.sql.db.postgresql.PostgreSQLConnection import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder import com.github.jasync.sql.db.util.length -import fr.postgresjson.entity.EntityI -import fr.postgresjson.entity.Serializable import fr.postgresjson.serializer.Serializer import fr.postgresjson.utils.LoggerDelegate +import kotlin.jvm.Throws import org.slf4j.Logger import kotlin.random.Random +import kotlin.reflect.full.hasAnnotation -typealias SelectOneCallback = QueryResult.(T?) -> Unit -typealias SelectCallback = QueryResult.(List) -> Unit -typealias SelectPaginatedCallback = QueryResult.(Paginated) -> Unit +// TODO move execute function outside +// TODO create function executeNullable class Connection( private val database: String, @@ -25,18 +23,18 @@ class Connection( private val password: String, private val host: String = "localhost", private val port: Int = 5432 -) : Executable { - private var connection: ConnectionPool? = null +) : ExecutableRaw { + private var connectionPool: ConnectionPool? = null private val serializer = Serializer() private val logger: Logger? by LoggerDelegate() internal fun connect(): ConnectionPool { - return connection.let { connectionPool -> + return connectionPool.let { connectionPool -> if (connectionPool == null || !connectionPool.isConnected()) { PostgreSQLConnectionBuilder.createConnectionPool( "jdbc:postgresql://$host:$port/$database?user=$username&password=$password" ).also { - connection = it + this.connectionPool = it } } else { connectionPool @@ -45,7 +43,7 @@ class Connection( } fun disconnect() { - connection?.disconnect() + connectionPool?.disconnect() } fun inTransaction(block: Connection.() -> A?): A? = connect().run { @@ -59,16 +57,19 @@ class Connection( } /** - * Select One [EntityI] with [List] of parameters + * Select with unnamed parameters */ - override fun selectOne( + @Throws(DataNotFoundException::class) + override fun execute( sql: String, typeReference: TypeReference, values: List, - block: (QueryResult, R?) -> Unit + block: SelectCallback ): R? { - val result = exec(sql, compileArgs(values)) - val json = result.rows.firstOrNull()?.getString(0) + val result: QueryResult = exec(sql, compileArgs(values)) + if (result.rows.size == 0) throw DataNotFoundException(sql) + + val json: String? = result.rows.firstOrNull()?.getString(0) return if (json === null) { null } else { @@ -79,119 +80,16 @@ class Connection( } /** - * Select One [EntityI] with named parameters + * Select with named parameters */ - override fun selectOne( + override fun execute( sql: String, typeReference: TypeReference, values: Map, - block: (QueryResult, R?) -> Unit + block: SelectCallback ): R? { return replaceArgs(sql, values) { - selectOne(this.sql, typeReference, parameters, block) - } - } - - /* Select Multiples */ - - /** - * Select multiple [EntityI] with [List] of parameters - */ - override fun select( - sql: String, - typeReference: TypeReference>, - values: List, - block: QueryResult.(List) -> Unit - ): List { - val result = exec(sql, values) - val json = result.rows[0].getString(0) - return if (json === null) { - emptyList() - } else { - serializer.deserializeList(json, typeReference) - }.also { - block(result, it) - } - } - - /** - * Select multiple [EntityI] with [Map] of parameters - */ - override fun select( - sql: String, - typeReference: TypeReference>, - values: Map, - block: QueryResult.(List) -> Unit - ): List { - return replaceArgs(sql, values) { - select(this.sql, typeReference, this.parameters, block) - } - } - - /** - * Select multiple or one [EntityI] with [Map] of parameters - */ - override fun selectAny( - sql: String, - typeReference: TypeReference, - values: Map, - block: QueryResult.(R) -> Unit - ): R { - val result = exec(sql, values) - val json = result.rows[0].getString(0) - return if (json === null) { - null as R - } else { - serializer.deserialize(json, typeReference) - }.also { - block(result, it) - } - } - - /* Select Paginated */ - - /** - * Select Multiple [EntityI] with pagination - */ - override fun select( - sql: String, - page: Int, - limit: Int, - typeReference: TypeReference>, - values: Map, - block: QueryResult.(Paginated) -> Unit - ): Paginated { - val offset = (page - 1) * limit - val newValues = values - .plus("offset" to offset) - .plus("limit" to limit) - - val line = replaceArgs(sql, newValues) { - exec(this.sql, this.parameters) - } - - return line.run { - val firstLine = rows.firstOrNull() ?: queryError("The query has no return", sql, newValues) - if (!rows.columnNames().contains("total")) queryError("""The query not return the "total" column""", sql, newValues, rows) - val total = try { - firstLine.getInt("total") ?: queryError("The query return \"total\" must not be null", sql, newValues, rows) - } catch (e: ClassCastException) { - queryError("""Column "total" must be an integer""", sql, newValues, rows) - } - val json = firstLine.getString(0) - val entities = if (json == null) { - emptyList() - } else { - serializer.deserializeList(json, typeReference) - } - Paginated( - entities, - offset, - limit, - total - ) - }.also { - block(line, it) + execute(this.sql, typeReference, parameters, block) } } @@ -231,10 +129,12 @@ class Connection( private fun compileArgs(values: List): List { return values.map { - if (it is Serializable || (it is List<*> && it.firstOrNull() is Serializable)) { - serializer.serialize(it) - } else { - it + when { + it == null -> it + it is List<*> && it.isEmpty() -> it + it is List<*> && it.first()!!::class.hasAnnotation() -> serializer.serialize(it) + it::class.hasAnnotation() -> serializer.serialize(it) + else -> it } } } diff --git a/src/main/kotlin/fr/postgresjson/connexion/DataNotFoundException.kt b/src/main/kotlin/fr/postgresjson/connexion/DataNotFoundException.kt new file mode 100644 index 0000000..7a853df --- /dev/null +++ b/src/main/kotlin/fr/postgresjson/connexion/DataNotFoundException.kt @@ -0,0 +1,6 @@ +package fr.postgresjson.connexion + +class DataNotFoundException(val queryExecuted: String): Exception() { + override val message: String + get() = "No data return for the query" +} \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt index eaccfe1..89e92c4 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt @@ -2,116 +2,43 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference import com.github.jasync.sql.db.QueryResult -import fr.postgresjson.entity.EntityI +import kotlin.jvm.Throws -sealed interface EmbedExecutable { +sealed interface EmbedExecutable : Executable { val connection: Connection override fun toString(): String val name: String - /* Select One */ - /** - * Update [EntityI] with one entity as argument + * Select with unnamed parameters */ - fun update( - typeReference: TypeReference, - value: R, - block: SelectOneCallback = {} - ): R? = - selectOne(typeReference, listOf(value), block) - - /** - * Select One [EntityI] with [List] of parameters - */ - fun selectOne( + @Throws(DataNotFoundException::class) + fun execute( typeReference: TypeReference, values: List, - block: SelectOneCallback = {} + block: SelectCallback = {} ): R? /** - * Select One [EntityI] with [Map] of parameters + * Select with named parameters */ - fun selectOne( + @Throws(DataNotFoundException::class) + fun execute( typeReference: TypeReference, values: Map, - block: SelectOneCallback = {} + block: SelectCallback = {} ): R? /** - * Select One [EntityI] with multiple [Pair] of parameters + * Select with named parameters */ - fun selectOne( + @Throws(DataNotFoundException::class) + fun execute( typeReference: TypeReference, vararg values: Pair, - block: SelectOneCallback = {} + block: SelectCallback = {} ): R? = - selectOne(typeReference, values.toMap(), block) - - /* Select Multiples */ - - /** - * Select Multiple [EntityI] with [List] of parameters - */ - fun select( - typeReference: TypeReference>, - values: List, - block: SelectCallback = {} - ): List - - /** - * Select Multiple [EntityI] with [Map] of parameters - */ - fun select( - typeReference: TypeReference>, - values: Map, - block: SelectCallback = {} - ): List - - /** - * Select Multiple [EntityI] with multiple [Pair] of parameters - */ - fun select( - typeReference: TypeReference>, - vararg values: Pair, - block: SelectCallback = {} - ): List = - select(typeReference, values.toMap(), block) - - /** - * Select Multiple or One [EntityI] with multiple [Pair] of parameters - */ - fun selectAny( - typeReference: TypeReference, - values: Map, - block: QueryResult.(R) -> Unit = {} - ): R - - /* Select Paginated */ - - /** - * Select Paginated [EntityI] with [Map] of parameters - */ - fun select( - page: Int, - limit: Int, - typeReference: TypeReference>, - values: Map, - block: SelectPaginatedCallback = {} - ): Paginated - - /** - * Select Paginated [EntityI] with multiple [Pair] of parameters - */ - fun select( - page: Int, - limit: Int, - typeReference: TypeReference>, - vararg values: Pair, - block: SelectPaginatedCallback = {} - ): Paginated = - select(page, limit, typeReference, values.toMap(), block) + execute(typeReference, values.toMap(), block) fun exec(values: List): QueryResult fun exec(values: Map): QueryResult diff --git a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutableReified.kt b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutableReified.kt index 73e4df4..4df0e8b 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutableReified.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutableReified.kt @@ -1,68 +1,25 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import fr.postgresjson.entity.EntityI +import kotlin.jvm.Throws -/* Select One */ - -inline fun EmbedExecutable.update( - value: R, - noinline block: SelectOneCallback = {} -): R? = - update(object : TypeReference() {}, value, block) - -inline fun EmbedExecutable.selectOne( - values: List, - noinline block: SelectOneCallback = {} -): R? = - selectOne(object : TypeReference() {}, values, block) - -inline fun EmbedExecutable.selectOne( - values: Map, - noinline block: SelectOneCallback = {} -): R? = - selectOne(object : TypeReference() {}, values, block) - -inline fun EmbedExecutable.selectOne( - vararg values: Pair, - noinline block: SelectOneCallback = {} -): R? = - selectOne(object : TypeReference() {}, values = values, block) - -/* Select Multiples */ - -inline fun EmbedExecutable.select( +@Throws(DataNotFoundException::class) +inline fun EmbedExecutable.execute( values: List, noinline block: SelectCallback = {} -): List = - select(object : TypeReference>() {}, values, block) +): R? = + execute(object : TypeReference() {}, values, block) -inline fun EmbedExecutable.select( +@Throws(DataNotFoundException::class) +inline fun EmbedExecutable.execute( values: Map, noinline block: SelectCallback = {} -): List = - select(object : TypeReference>() {}, values, block) +): R? = + execute(object : TypeReference() {}, values, block) -inline fun EmbedExecutable.select( +@Throws(DataNotFoundException::class) +inline fun EmbedExecutable.execute( vararg values: Pair, noinline block: SelectCallback = {} -): List = - select(object : TypeReference>() {}, values = values, block) - -/* Select Paginated */ - -inline fun EmbedExecutable.select( - page: Int, - limit: Int, - values: Map = emptyMap(), - noinline block: SelectPaginatedCallback = {} -): Paginated = - select(page, limit, object : TypeReference>() {}, values, block) - -inline fun EmbedExecutable.select( - page: Int, - limit: Int, - vararg values: Pair, - noinline block: SelectPaginatedCallback = {} -): Paginated = - select(page, limit, object : TypeReference>() {}, values = values, block) +): R? = + execute(object : TypeReference() {}, values = values, block) diff --git a/src/main/kotlin/fr/postgresjson/connexion/Executable.kt b/src/main/kotlin/fr/postgresjson/connexion/Executable.kt index 0c240ae..83d4095 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Executable.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Executable.kt @@ -1,146 +1,3 @@ package fr.postgresjson.connexion -import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.QueryResult -import fr.postgresjson.entity.EntityI - -interface Executable { - - /* Update */ - - /** - * Update [EntityI] with one entity as argument - */ - fun update( - sql: String, - typeReference: TypeReference, - value: R, - block: SelectOneCallback = {} - ): R? = - selectOne(sql, typeReference, listOf(value), block) - - /* Select One */ - - /** - * Select One [EntityI] with [List] of parameters - */ - fun selectOne( - sql: String, - typeReference: TypeReference, - values: List, - block: SelectOneCallback = {} - ): R? - - /** - * Select One [EntityI] with [Map] of parameters - */ - fun selectOne( - sql: String, - typeReference: TypeReference, - values: Map, - block: SelectOneCallback = {} - ): R? - - /** - * Select One [EntityI] with multiple [Pair] of parameters - */ - fun selectOne( - sql: String, - typeReference: TypeReference, - vararg values: Pair, - block: SelectOneCallback = {} - ): R? = - selectOne(sql, typeReference, values.toMap(), block) - - /* Select Multiples */ - - /** - * Select Multiple [EntityI] with [List] of parameters - */ - fun select( - sql: String, - typeReference: TypeReference>, - values: List = emptyList(), - block: SelectCallback = {} - ): List - - /** - * Select Multiple [EntityI] with [Map] of parameters - */ - fun select( - sql: String, - typeReference: TypeReference>, - values: Map, - block: SelectCallback = {} - ): List - - /** - * Select Multiple or One [EntityI] with [Map] of parameters - */ - fun selectAny( - sql: String, - typeReference: TypeReference, - values: Map, - block: QueryResult.(R) -> Unit = {} - ): R - - /** - * Select Multiple [EntityI] with multiple [Pair] of parameters - */ - fun select( - sql: String, - typeReference: TypeReference>, - vararg values: Pair, - block: SelectCallback = {} - ): List = - select(sql, typeReference, values.toMap(), block) - - /* Select Paginated */ - - /** - * Select Paginated [EntityI] with [Map] of parameters - */ - fun select( - sql: String, - page: Int, - limit: Int, - typeReference: TypeReference>, - values: Map, - block: SelectPaginatedCallback = {} - ): Paginated - - /** - * Select Paginated [EntityI] with multiple [Pair] of parameters - */ - fun select( - sql: String, - page: Int, - limit: Int, - typeReference: TypeReference>, - vararg values: Pair, - block: SelectPaginatedCallback = {} - ): Paginated = - select(sql, page, limit, typeReference, values.toMap(), block) - - fun exec(sql: String, value: R): QueryResult = exec(sql, listOf(value)) - fun exec(sql: String, values: List): QueryResult - fun exec(sql: String, values: Map): QueryResult - fun exec(sql: String, vararg values: Pair): QueryResult = exec(sql, values.toMap()) - - /** - * Warning: this method not use prepared statement - */ - fun sendQuery(sql: String, value: R): QueryResult = sendQuery(sql, listOf(value)) - /** - * Warning: this method not use prepared statement - */ - fun sendQuery(sql: String, values: List): QueryResult - /** - * Warning: this method not use prepared statement - */ - fun sendQuery(sql: String, values: Map): QueryResult - /** - * Warning: this method not use prepared statement - */ - fun sendQuery(sql: String, vararg values: Pair): QueryResult = sendQuery(sql, values.toMap()) -} +sealed interface Executable \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/connexion/ExecutableRaw.kt b/src/main/kotlin/fr/postgresjson/connexion/ExecutableRaw.kt new file mode 100644 index 0000000..2cafb96 --- /dev/null +++ b/src/main/kotlin/fr/postgresjson/connexion/ExecutableRaw.kt @@ -0,0 +1,76 @@ +package fr.postgresjson.connexion + +import com.fasterxml.jackson.core.type.TypeReference +import com.github.jasync.sql.db.QueryResult +import kotlin.jvm.Throws + +typealias SelectCallback = QueryResult.(R?) -> Unit + +sealed interface ExecutableRaw : Executable { + /** + * Select with one entity as argument + */ + @Throws(DataNotFoundException::class) + fun execute( + sql: String, + typeReference: TypeReference, + value: R, + block: SelectCallback = {} + ): R? = + execute(sql, typeReference, listOf(value), block) + + /** + * Select with [List] of parameters + */ + @Throws(DataNotFoundException::class) + fun execute( + sql: String, + typeReference: TypeReference, + values: List = emptyList(), + block: SelectCallback = {} + ): R? + + /** + * Select with [Map] of parameters + */ + @Throws(DataNotFoundException::class) + fun execute( + sql: String, + typeReference: TypeReference, + values: Map, + block: SelectCallback = {} + ): R? + + /** + * Select with multiple [Pair] of parameters + */ + @Throws(DataNotFoundException::class) + fun execute( + sql: String, + typeReference: TypeReference, + vararg values: Pair, + block: SelectCallback = {} + ): R? = execute(sql, typeReference, values.toMap(), block) + + fun exec(sql: String, value: R): QueryResult = exec(sql, listOf(value)) + fun exec(sql: String, values: List): QueryResult + fun exec(sql: String, values: Map): QueryResult + fun exec(sql: String, vararg values: Pair): QueryResult = exec(sql, values.toMap()) + + /** + * Warning: this method not use prepared statement + */ + fun sendQuery(sql: String, value: R): QueryResult = sendQuery(sql, listOf(value)) + /** + * Warning: this method not use prepared statement + */ + fun sendQuery(sql: String, values: List): QueryResult + /** + * Warning: this method not use prepared statement + */ + fun sendQuery(sql: String, values: Map): QueryResult + /** + * Warning: this method not use prepared statement + */ + fun sendQuery(sql: String, vararg values: Pair): QueryResult = sendQuery(sql, values.toMap()) +} diff --git a/src/main/kotlin/fr/postgresjson/connexion/ExecutableReified.kt b/src/main/kotlin/fr/postgresjson/connexion/ExecutableReified.kt index 25686e1..0f5cb45 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/ExecutableReified.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/ExecutableReified.kt @@ -1,106 +1,37 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import fr.postgresjson.entity.EntityI - -/* Update */ +import kotlin.jvm.Throws /** - * Update [EntityI] with one entity as argument + * Select with unnamed parameters */ -inline fun Executable.update( - sql: String, - value: R, - noinline block: SelectOneCallback = {} -): R? = - update(sql, object : TypeReference() {}, value, block) - -/* Select One */ - -/** - * Select One [EntityI] with [List] of parameters - */ -inline fun Executable.selectOne( - sql: String, - values: List = emptyList(), - noinline block: SelectOneCallback = {} -): R? = - selectOne(sql, object : TypeReference() {}, values, block) - -/** - * Select One [EntityI] with [Map] of parameters - */ -inline fun Executable.selectOne( - sql: String, - values: Map, - noinline block: SelectOneCallback = {} -): R? = - selectOne(sql, object : TypeReference() {}, values, block) - -/** - * Select One [EntityI] with multiple [Pair] of parameters - */ -inline fun Executable.selectOne( - sql: String, - vararg values: Pair, - noinline block: SelectOneCallback = {} -): R? = - selectOne(sql, object : TypeReference() {}, values = values, block) - -/* Select Multiples */ - -/** - * Select Multiple [EntityI] with [List] of parameters - */ -inline fun Executable.select( +@Throws(DataNotFoundException::class) +inline fun ExecutableRaw.execute( sql: String, values: List = emptyList(), noinline block: SelectCallback = {} -): List = - select(sql, object : TypeReference>() {}, values, block) +): R? = + execute(sql, object : TypeReference() {}, values, block) /** - * Select Multiple [EntityI] with [Map] of parameters + * Select with named parameters */ -inline fun Executable.select( +@Throws(DataNotFoundException::class) +inline fun ExecutableRaw.execute( sql: String, values: Map, noinline block: SelectCallback = {} -): List = - select(sql, object : TypeReference>() {}, values, block) +): R? = + execute(sql, object : TypeReference() {}, values, block) /** - * Select Multiple [EntityI] with multiple [Pair] of parameters + * Select with named parameters */ -inline fun Executable.select( +@Throws(DataNotFoundException::class) +inline fun ExecutableRaw.execute( sql: String, vararg values: Pair, noinline block: SelectCallback = {} -): List = - select(sql, object : TypeReference>() {}, values = values, block) - -/* Select Paginated */ - -/** - * Select Paginated [EntityI] with [Map] of parameters - */ -inline fun Executable.select( - sql: String, - page: Int, - limit: Int, - values: Map = emptyMap(), - noinline block: SelectPaginatedCallback = {} -): Paginated = - select(sql, page, limit, object : TypeReference>() {}, values, block) - -/** - * Select Paginated [EntityI] with multiple [Pair] of parameters - */ -inline fun Executable.select( - sql: String, - page: Int, - limit: Int, - vararg values: Pair, - noinline block: SelectPaginatedCallback = {} -): Paginated = - select(sql, page, limit, object : TypeReference>() {}, values = values, block) +): R? = + execute(sql, object : TypeReference() {}, values = values, block) diff --git a/src/main/kotlin/fr/postgresjson/connexion/Function.kt b/src/main/kotlin/fr/postgresjson/connexion/Function.kt index e2bce37..d025bfa 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Function.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Function.kt @@ -3,7 +3,6 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference import com.github.jasync.sql.db.QueryResult import fr.postgresjson.definition.Function -import fr.postgresjson.entity.EntityI class Function(val definition: Function, override val connection: Connection) : EmbedExecutable { override fun toString(): String { @@ -12,86 +11,42 @@ class Function(val definition: Function, override val connection: Connection) : override val name: String = definition.name - /* Select One */ - /** - * Select One [EntityI] with [List] of parameters + * Select with [List] of parameters */ - override fun selectOne( + override fun execute( typeReference: TypeReference, values: List, - block: (QueryResult, R?) -> Unit + block: SelectCallback ): R? = - connection.selectOne(compileSql(values), typeReference, values, block) + connection.execute(compileSql(values), typeReference, values, block) /** - * Select One [EntityI] with named parameters + * Select with named parameters */ - override fun selectOne( + override fun execute( typeReference: TypeReference, values: Map, - block: (QueryResult, R?) -> Unit + block: SelectCallback ): R? = - connection.selectOne(compileSql(values), typeReference, values, block) - - /* Select Multiples */ + connection.execute(compileSql(values), typeReference, values, block) /** - * Select multiple [EntityI] with [List] of parameters + * Execute function without treatments */ - override fun select( - typeReference: TypeReference>, - values: List, - block: (QueryResult, List) -> Unit - ): List = - connection.select(compileSql(values), typeReference, values, block) - - /** - * Select multiple [EntityI] with named parameters - */ - override fun select( - typeReference: TypeReference>, - values: Map, - block: (QueryResult, List) -> Unit - ): List = - connection.select(compileSql(values), typeReference, values, block) - - override fun selectAny( - typeReference: TypeReference, - values: Map, - block: QueryResult.(R) -> Unit - ): R = - connection.selectAny(compileSql(values.toMap()), typeReference, values.toMap(), block) - - /* Select Paginated */ - - /** - * Select Multiple [EntityI] with pagination - */ - override fun select( - page: Int, - limit: Int, - typeReference: TypeReference>, - values: Map, - block: (QueryResult, Paginated) -> Unit - ): Paginated { - val offset = (page - 1) * limit - val newValues = values - .plus("offset" to offset) - .plus("limit" to limit) - - return connection.select(compileSql(newValues), page, limit, typeReference, values, block) - } - - /* Execute function without treatments */ - override fun exec(values: List): QueryResult = connection.exec(compileSql(values), values) + /** + * Execute function without treatments + */ override fun exec(values: Map): QueryResult = connection.exec(compileSql(values), values) - private fun compileArgs(value: R): String = compileArgs(listOf(value)) + private fun compileParameters(value: A): String = compileParameters(listOf(value)) - private fun compileArgs(values: List): String { + /** + * Add cast to all parameters + */ + private fun compileParameters(values: List): String { val placeholders = values .filterIndexed { index, value -> definition.parameters[index].default === null || value != null @@ -103,7 +58,10 @@ class Function(val definition: Function, override val connection: Connection) : return placeholders.joinToString(separator = ", ") } - private fun compileArgs(values: Map): String { + /** + * Cast and add named parameters + */ + private fun compileParameters(values: Map): String { val parameters = definition.getParametersIndexedByName() val placeholders = values .filter { entry -> @@ -118,7 +76,16 @@ class Function(val definition: Function, override val connection: Connection) : return placeholders.joinToString(separator = ", ") } - private fun compileSql(value: R): String = "SELECT * FROM ${definition.name} (${compileArgs(value)})" - private fun compileSql(values: List): String = "SELECT * FROM ${definition.name} (${compileArgs(values)})" - private fun compileSql(values: Map): String = "SELECT * FROM ${definition.name} (${compileArgs(values)})" + /** + * Create SQL to call the function + */ + private fun compileSql(value: A): String = "SELECT * FROM ${definition.name} (${compileParameters(value)})" + /** + * Create SQL to call the function + */ + private fun compileSql(values: List): String = "SELECT * FROM ${definition.name} (${compileParameters(values)})" + /** + * Create SQL to call the function + */ + private fun compileSql(values: Map): String = "SELECT * FROM ${definition.name} (${compileParameters(values)})" } diff --git a/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt b/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt deleted file mode 100644 index f755b1e..0000000 --- a/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt +++ /dev/null @@ -1,25 +0,0 @@ -package fr.postgresjson.connexion - -import fr.postgresjson.entity.EntityI -import kotlin.math.ceil - -data class Paginated( - val result: List, - val offset: Int, - val limit: Int, - val total: Int -) { - val currentPage: Int = (offset / limit) + 1 - val count: Int = result.size - val totalPages: Int = (total.toDouble() / limit.toDouble()).ceil() - - init { - if (offset < 0) error("offset must be greater or equal than 0") - if (limit < 1) error("limit must be greater or equal than 1") - if (total < 0) error("total must be greater or equal than 0") - } - - fun isLastPage(): Boolean = currentPage >= totalPages - - private fun Double.ceil(): Int = ceil(this).toInt() -} diff --git a/src/main/kotlin/fr/postgresjson/connexion/Query.kt b/src/main/kotlin/fr/postgresjson/connexion/Query.kt index 3d23d9b..2adffb1 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Query.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Query.kt @@ -2,81 +2,40 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference import com.github.jasync.sql.db.QueryResult -import fr.postgresjson.entity.EntityI class Query(override val name: String, private val sql: String, override val connection: Connection) : EmbedExecutable { override fun toString(): String { return sql } - /* Select One */ - /** - * Select One [EntityI] with [List] of parameters + * Select with unnamed of parameters */ - override fun selectOne( + override fun execute( typeReference: TypeReference, values: List, - block: SelectOneCallback + block: SelectCallback ): R? = - connection.selectOne(sql, typeReference, values, block) + connection.execute(sql, typeReference, values, block) /** - * Select One [EntityI] with named parameters + * Select with named parameters */ - override fun selectOne( + override fun execute( typeReference: TypeReference, values: Map, - block: SelectOneCallback + block: SelectCallback ): R? = - connection.selectOne(sql, typeReference, values, block) - - /* Select Multiples */ + connection.execute(sql, typeReference, values, block) /** - * Select multiple [EntityI] with [List] of parameters + * Execute function without treatments */ - override fun select( - typeReference: TypeReference>, - values: List, - block: SelectCallback - ): List = - connection.select(sql, typeReference, values, block) - - /** - * Select multiple [EntityI] with [Map] of parameters - */ - override fun select( - typeReference: TypeReference>, - values: Map, - block: SelectCallback - ): List = - connection.select(sql, typeReference, values, block) - - /* Select Paginated */ - - /** - * Select Multiple [EntityI] with pagination - */ - override fun select( - page: Int, - limit: Int, - typeReference: TypeReference>, - values: Map, - block: (QueryResult, Paginated) -> Unit - ): Paginated = - connection.select(sql, page, limit, typeReference, values, block) - - override fun selectAny( - typeReference: TypeReference, - values: Map, - block: QueryResult.(R) -> Unit - ): R = connection.selectAny(sql, typeReference, values.toMap(), block) - - /* Execute function without treatments */ - override fun exec(values: List): QueryResult = connection.exec(sql, values) + /** + * Execute function without treatments + */ override fun exec(values: Map): QueryResult = connection.exec(sql, values) /** @@ -88,6 +47,7 @@ class Query(override val name: String, private val sql: String, override val con * Warning: this method not use prepared statement */ fun sendQuery(values: Map): QueryResult = connection.sendQuery(sql, values) + /** * Warning: this method not use prepared statement */ diff --git a/src/main/kotlin/fr/postgresjson/connexion/QueryConverter.kt b/src/main/kotlin/fr/postgresjson/connexion/QueryConverter.kt index ca975b2..c1e99b8 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/QueryConverter.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/QueryConverter.kt @@ -4,12 +4,24 @@ import fr.postgresjson.utils.searchSqlFiles import java.net.URI import fr.postgresjson.definition.Query as QueryDefinition +/** + * Convert [QueryDefinition], to runnable [Query] + */ fun QueryDefinition.toRunnable(connection: Connection): Query = Query(name, script, connection) +/** + * Convert Sequence of [QueryDefinition], to runnable Sequence of [Query] + */ fun Sequence.toRunnable(connection: Connection): Sequence = map { it.toRunnable(connection) } +/** + * Convert Sequence of [Query], to [Map] of [Query] with name as key + */ fun Sequence.toMutableMap(): MutableMap = map { it.name to it }.toMap().toMutableMap() +/** + * Create a [Map] of [Query] from a [URI] pointing to the queries folder + */ internal fun URI.toQuery(connection: Connection): MutableMap = searchSqlFiles() .filterIsInstance(QueryDefinition::class.java) .toRunnable(connection) diff --git a/src/main/kotlin/fr/postgresjson/connexion/SqlSerializable.kt b/src/main/kotlin/fr/postgresjson/connexion/SqlSerializable.kt new file mode 100644 index 0000000..b6b68a8 --- /dev/null +++ b/src/main/kotlin/fr/postgresjson/connexion/SqlSerializable.kt @@ -0,0 +1,4 @@ +package fr.postgresjson.connexion + +@Target(AnnotationTarget.CLASS) +annotation class SqlSerializable diff --git a/src/main/kotlin/fr/postgresjson/entity/EntitiesInterfaces.kt b/src/main/kotlin/fr/postgresjson/entity/EntitiesInterfaces.kt deleted file mode 100644 index f86bc25..0000000 --- a/src/main/kotlin/fr/postgresjson/entity/EntitiesInterfaces.kt +++ /dev/null @@ -1,126 +0,0 @@ -package fr.postgresjson.entity - -import org.joda.time.DateTime -import java.util.UUID - -interface EntityRefI : EntityI { - val id: T -} - -interface UuidEntityI : EntityRefI { - override val id: UUID -} - -abstract class Entity(override val id: T) : EntityRefI -open class UuidEntity(id: UUID? = null) : UuidEntityI, Entity(id ?: UUID.randomUUID()) - -/* Version */ -interface EntityVersioning { - val versionNumber: NUMBER - val versionId: ID -} - -class UuidEntityVersioning( - override val versionNumber: Int, - versionId: UUID? = null -) : EntityVersioning { - override val versionId: UUID = versionId ?: UUID.randomUUID() -} - -/* Dates */ -interface EntityCreatedAt { - val createdAt: DateTime -} -interface EntityUpdatedAt { - val updatedAt: DateTime -} - -interface EntityDeletedAt { - val deletedAt: DateTime? - fun isDeleted(): Boolean { - return deletedAt?.let { - it < DateTime.now() - } ?: false - } -} - -class EntityCreatedAtImp( - override val createdAt: DateTime = DateTime.now() -) : EntityCreatedAt - -class EntityUpdatedAtImp( - override val updatedAt: DateTime = DateTime.now() -) : EntityUpdatedAt - -class EntityDeletedAtImp( - override val deletedAt: DateTime? = null -) : EntityDeletedAt - -/* Author */ -interface EntityCreatedBy { - val createdBy: T -} -interface EntityUpdatedBy { - val updatedBy: T -} - -interface EntityDeletedBy { - val deletedBy: T? -} - -class EntityCreatedByImp( - override val createdBy: UserT -) : EntityCreatedBy - -class EntityUpdatedByImp( - override val updatedBy: UserT -) : EntityUpdatedBy - -class EntityDeletedByImp( - override val deletedBy: UserT? -) : EntityDeletedBy - -/* Mixed */ -class EntityCreatedImp( - override val createdAt: DateTime = DateTime.now(), - createdBy: UserT -) : EntityCreatedBy by EntityCreatedByImp(createdBy), - EntityCreatedAt by EntityCreatedAtImp() - -class EntityUpdatedImp( - updatedAt: DateTime = DateTime.now(), - override val updatedBy: UserT -) : EntityUpdatedBy, - EntityUpdatedAt by EntityUpdatedAtImp(updatedAt) - -/* Published */ -interface Published { - val publishedAt: DateTime? - val publishedBy: UserT? -} - -class EntityPublishedImp( - override val publishedBy: UserT? -) : Published { - override val publishedAt: DateTime? = null -} - -/* Implementation */ -abstract class EntityImp( - updatedBy: UserT, - updatedAt: DateTime = DateTime.now() -) : UuidEntity(), - EntityCreatedAt by EntityCreatedAtImp(updatedAt), - EntityUpdatedAt by EntityUpdatedAtImp(updatedAt), - EntityDeletedAt by EntityDeletedAtImp(), - EntityCreatedBy by EntityCreatedByImp(updatedBy), - EntityUpdatedBy by EntityUpdatedByImp(updatedBy), - EntityDeletedBy by EntityDeletedByImp(updatedBy) - -abstract class UuidEntityExtended( - updatedBy: UserT, - publishedBy: UserT? -) : - EntityImp(updatedBy), - EntityVersioning by UuidEntityVersioning(0), - Published by EntityPublishedImp(publishedBy) diff --git a/src/main/kotlin/fr/postgresjson/entity/Entity.kt b/src/main/kotlin/fr/postgresjson/entity/Entity.kt deleted file mode 100644 index 0ca917a..0000000 --- a/src/main/kotlin/fr/postgresjson/entity/Entity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package fr.postgresjson.entity - -interface Serializable -interface EntityI : Serializable -interface Parameter : Serializable diff --git a/src/main/kotlin/fr/postgresjson/functionGenerator/FunctionGenerator.kt b/src/main/kotlin/fr/postgresjson/functionGenerator/FunctionGenerator.kt index 770f0d3..583f0bf 100644 --- a/src/main/kotlin/fr/postgresjson/functionGenerator/FunctionGenerator.kt +++ b/src/main/kotlin/fr/postgresjson/functionGenerator/FunctionGenerator.kt @@ -103,23 +103,21 @@ class FunctionGenerator(private val functionsDirectories: List) { val hasReturn: Boolean = parameters.any { it.direction != IN } || (returns != "" && returns != "void") val generics = mutableListOf() - if (hasReturn) generics.add("reified E: Any?") - if (hasInputArgs) generics.add("S: Serializable") + if (hasReturn) generics.add("reified E: Any") + if (hasInputArgs) generics.add("S: Any?") val functionDecl = if (generics.isNotEmpty()) "inline fun <${generics.joinToString(", ")}>" else "fun" - val importSerializable = if (hasInputArgs) "import fr.postgresjson.entity.Serializable\n" else "" - if (hasReturn) { return """ |package fr.postgresjson.functionGenerator.generated | |import com.fasterxml.jackson.core.type.TypeReference |import fr.postgresjson.connexion.Requester - |$importSerializable - |$functionDecl Requester.$kotlinName($args): E { + | + |$functionDecl Requester.$kotlinName($args): E? { | return getFunction("$name") - | .selectAny(object : TypeReference() {}, ${parameters.toMapOf()}) + | .execute(object : TypeReference() {}, ${parameters.toMapOf()}) |} """.trimMargin() } else { @@ -127,7 +125,7 @@ class FunctionGenerator(private val functionsDirectories: List) { |package fr.postgresjson.functionGenerator.generated | |import fr.postgresjson.connexion.Requester - |$importSerializable + | |$functionDecl Requester.$kotlinName($args): Unit { | getFunction("$name") | .exec(${parameters.toMapOf()}) diff --git a/src/main/kotlin/fr/postgresjson/migration/Function.kt b/src/main/kotlin/fr/postgresjson/migration/Function.kt index 73f445a..367ee8a 100644 --- a/src/main/kotlin/fr/postgresjson/migration/Function.kt +++ b/src/main/kotlin/fr/postgresjson/migration/Function.kt @@ -2,7 +2,7 @@ package fr.postgresjson.migration import com.github.jasync.sql.db.postgresql.exceptions.GenericDatabaseException import fr.postgresjson.connexion.Connection -import fr.postgresjson.connexion.selectOne +import fr.postgresjson.connexion.execute import fr.postgresjson.migration.Migration.Action import fr.postgresjson.migration.Migration.Status import java.util.Date @@ -50,11 +50,11 @@ data class Function( this::class.java.classLoader .getResource("sql/migration/insertFunction.sql")!!.readText() - .let { connection.selectOne(it, listOf(up.name, up.getDefinition(), up.script, down.script)) } - ?.let { function -> - executedAt = function.executedAt + .let { connection.execute(it, listOf(up.name, up.getDefinition(), up.script, down.script)) } + ?.let { migration: MigrationEntity -> + executedAt = migration.executedAt doExecute = Action.OK - } + } ?: error("No migration executed") Status.OK } catch (e: Throwable) { diff --git a/src/main/kotlin/fr/postgresjson/migration/MigrationScript.kt b/src/main/kotlin/fr/postgresjson/migration/MigrationScript.kt index 7092879..6a66cd2 100644 --- a/src/main/kotlin/fr/postgresjson/migration/MigrationScript.kt +++ b/src/main/kotlin/fr/postgresjson/migration/MigrationScript.kt @@ -1,9 +1,9 @@ package fr.postgresjson.migration import fr.postgresjson.connexion.Connection -import fr.postgresjson.connexion.selectOne -import fr.postgresjson.entity.Entity +import fr.postgresjson.connexion.execute import fr.postgresjson.migration.Migration.Action +import fr.postgresjson.migration.Migration.Status import java.util.Date data class MigrationScript( @@ -12,40 +12,44 @@ data class MigrationScript( val down: String, private val connection: Connection, override var executedAt: Date? = null -) : Migration, Entity(name) { +) : Migration { override var doExecute: Action? = null - override fun up(): Migration.Status { - connection.sendQuery(up) + override fun up(): Status { + return try { + connection.sendQuery(up) - this::class.java.classLoader.getResource("sql/migration/insertHistory.sql")!!.readText().let { - connection.selectOne(it, listOf(name, up, down))?.let { query -> - executedAt = query.executedAt - doExecute = Action.OK + this::class.java.classLoader.getResource("sql/migration/insertHistory.sql")!!.readText().let { + connection.execute(it, listOf(name, up, down))?.let { query -> + executedAt = query.executedAt + doExecute = Action.OK + } ?: error("No migration executed") } - } - return Migration.Status.OK + Status.OK + } catch (e: Throwable) { + Status.UP_FAIL + } } - override fun down(): Migration.Status { + override fun down(): Status { connection.sendQuery(down) this::class.java.classLoader.getResource("sql/migration/deleteHistory.sql")!!.readText().let { connection.exec(it, listOf(name)) } - return Migration.Status.OK + return Status.OK } - override fun test(): Migration.Status { + override fun test(): Status { connection.inTransaction { up() down() sendQuery("ROLLBACK") } - return Migration.Status.OK + return Status.OK } fun copy(): MigrationScript { diff --git a/src/main/kotlin/fr/postgresjson/migration/Migrations.kt b/src/main/kotlin/fr/postgresjson/migration/Migrations.kt index 4c7d2cb..4e7cd8c 100644 --- a/src/main/kotlin/fr/postgresjson/migration/Migrations.kt +++ b/src/main/kotlin/fr/postgresjson/migration/Migrations.kt @@ -2,7 +2,6 @@ package fr.postgresjson.migration import com.fasterxml.jackson.core.type.TypeReference import fr.postgresjson.connexion.Connection -import fr.postgresjson.entity.Entity import fr.postgresjson.migration.Migration.Action import fr.postgresjson.migration.Migration.Status import fr.postgresjson.utils.LoggerDelegate @@ -20,7 +19,7 @@ class MigrationEntity( val up: String, val down: String, val version: Int -) : Entity(filename) +) interface Migration { var executedAt: Date? @@ -76,15 +75,15 @@ class Migrations private constructor( */ private fun getMigrationFromDB() { this::class.java.classLoader.getResource("sql/migration/findAllFunction.sql")!!.readText().let { - connection.select(it, object : TypeReference>() {}) - .map { function -> + connection.execute(it, object : TypeReference>() {}) + ?.map { function -> functions[function.filename] = Function(function.up, function.down, connection, function.executedAt) } } this::class.java.classLoader.getResource("sql/migration/findAllHistory.sql")!!.readText().let { - connection.select(it, object : TypeReference>() {}) - .map { query -> + connection.execute(it, object : TypeReference>() {}) + ?.map { query -> migrationsScripts[query.filename] = MigrationScript(query.filename, query.up, query.down, connection, query.executedAt) } } diff --git a/src/main/kotlin/fr/postgresjson/serializer/Serializer.kt b/src/main/kotlin/fr/postgresjson/serializer/Serializer.kt index 45a3da1..0725087 100644 --- a/src/main/kotlin/fr/postgresjson/serializer/Serializer.kt +++ b/src/main/kotlin/fr/postgresjson/serializer/Serializer.kt @@ -9,7 +9,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.datatype.joda.JodaModule import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.readValue -import fr.postgresjson.entity.Serializable +import com.github.jasync.sql.db.QueryResult class Serializer(val mapper: ObjectMapper = jacksonObjectMapper()) { init { @@ -44,8 +44,13 @@ class Serializer(val mapper: ObjectMapper = jacksonObjectMapper()) { } } -fun Serializable.serialize(pretty: Boolean = false) = Serializer().serialize(this, pretty) -fun List.serialize(pretty: Boolean = false) = Serializer().serialize(this, pretty) -inline fun String.deserialize() = Serializer().deserialize(this) +inline fun QueryResult.deserialize(): E? { + val value = this.rows.firstOrNull()?.getString(0) + return if (value == null) { + null + } else { + Serializer().deserialize(value) + } +} -inline fun T.toTypeReference(): TypeReference = object : TypeReference() {} +inline fun T.toTypeReference(): TypeReference = object : TypeReference() {} diff --git a/src/test/kotlin/fr/postgresjson/ConnectionTest.kt b/src/test/kotlin/fr/postgresjson/ConnectionTest.kt index bca640b..a619277 100644 --- a/src/test/kotlin/fr/postgresjson/ConnectionTest.kt +++ b/src/test/kotlin/fr/postgresjson/ConnectionTest.kt @@ -1,48 +1,59 @@ package fr.postgresjson import com.fasterxml.jackson.core.type.TypeReference -import fr.postgresjson.connexion.Connection.QueryError -import fr.postgresjson.connexion.Paginated -import fr.postgresjson.connexion.select -import fr.postgresjson.connexion.selectOne -import fr.postgresjson.entity.Parameter -import fr.postgresjson.entity.UuidEntity +import fr.postgresjson.connexion.DataNotFoundException +import fr.postgresjson.connexion.SqlSerializable +import fr.postgresjson.connexion.execute import fr.postgresjson.serializer.deserialize import fr.postgresjson.serializer.toTypeReference import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance -import org.junit.jupiter.api.assertThrows import java.util.UUID -import kotlin.test.assertContains +import kotlin.reflect.full.hasAnnotation import kotlin.test.assertEquals +import kotlin.test.assertFalse import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue +import org.junit.jupiter.api.assertThrows @TestInstance(TestInstance.Lifecycle.PER_CLASS) class ConnectionTest : TestAbstract() { - private class ObjTest(val name: String, id: UUID = UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00")) : UuidEntity(id) - private class ObjTest2(val title: String, var test: ObjTest?) : UuidEntity() - private class ObjTest3(val first: String, var second: String, var third: Int) : UuidEntity() - private class ObjTestWithParameterObject(var first: ParameterObject, var second: ParameterObject) : UuidEntity() - private class ParameterObject(var third: String) : Parameter + @SqlSerializable + private class ObjTest(val name: String, val id: UUID = UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00")) + @SqlSerializable + private class ObjTest2(val id: UUID, val title: String, var test: ObjTest?) + @SqlSerializable + private class ObjTest3(val id: UUID, val first: String, var second: String, var third: Int) + @SqlSerializable + private class ObjTestWithParameterObject(val id: UUID, var first: ParameterObject, var second: ParameterObject) + @SqlSerializable + private class ParameterObject(var third: String) + private class ObjTest4(var third: String) + + @Test + fun serializable() { + assertTrue(ObjTest("plop")::class.hasAnnotation()) + assertFalse(ObjTest4("plop")::class.hasAnnotation()) + } @Test fun getObject() { - val obj: ObjTest? = connection.selectOne("select to_json(a) from test a limit 1") - assertTrue(obj is ObjTest) + val obj: ObjTest? = connection.execute("select to_json(a) from test a limit 1") + assertNotNull(obj) assertEquals(UUID.fromString("1e5f5d41-6d14-4007-897b-0ed2616bec96"), obj.id) } @Test fun getExistingObject() { - val objs: List = connection.select( + val objs: List? = connection.execute>( """ select json_agg(j) FROM ( SELECT - t.id, t.title, + t.id, + t.title, t2 as test from test2 t JOIN test t2 ON t.test_id = t2.id @@ -57,15 +68,15 @@ class ConnectionTest : TestAbstract() { @Test fun `test call request with args`() { - val result: ObjTest? = connection.selectOne("select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', ?::text)", listOf("myName")) + val result: ObjTest? = connection.execute("select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', ?::text)", listOf("myName")) assertNotNull(result) assertEquals("myName", result.name) } @Test fun `test call request without args`() { - val result: ObjTest? = connection.selectOne("select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', 'myName')", object : TypeReference() {}) { - assertEquals("myName", this.rows[0].getString(0)?.deserialize()?.name) + val result: ObjTest? = connection.execute("select json_build_object('id', '2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00', 'name', 'myName')", object : TypeReference() {}) { + assertEquals("myName", this.deserialize()?.name) } assertNotNull(result) assertEquals("myName", result.name) @@ -73,20 +84,21 @@ class ConnectionTest : TestAbstract() { @Test fun `test call request return null`() { - val result: ObjTest? = connection.selectOne("select null;", object : TypeReference() {}) + val result: ObjTest? = connection.execute("select null;", object : TypeReference() {}) assertNull(result) } @Test fun `test call request return nothing`() { - val result: ObjTest? = connection.selectOne("select * from test where false;", object : TypeReference() {}) - assertNull(result) + assertThrows { + connection.execute("select * from test where false;", object : TypeReference() {}) + } } @Test fun callRequestWithArgsEntity() { val o = ObjTest("myName", id = UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00")) - val obj: ObjTest? = connection.selectOne("select json_build_object('id', id, 'name', name) FROM json_to_record(?::json) as o(id uuid, name text);", listOf(o)) + val obj: ObjTest? = connection.execute("select json_build_object('id', id, 'name', name) FROM json_to_record(?::json) as o(id uuid, name text);", listOf(o)) assertNotNull(obj) assertEquals(UUID.fromString("2c0243ed-ff4d-4b9f-a52b-e38c71b0ed00"), obj.id) assertEquals("myName", obj.name) @@ -95,8 +107,8 @@ class ConnectionTest : TestAbstract() { @Test fun `test update Entity`() { val obj = ObjTest("before", id = UUID.fromString("1e5f5d41-6d14-4007-897b-0ed2616bec96")) - val objUpdated: ObjTest? = connection.update("select ?::jsonb || jsonb_build_object('name', 'after');", obj.toTypeReference(), obj) - assertTrue(objUpdated is ObjTest) + val objUpdated: ObjTest? = connection.execute("select ?::jsonb || jsonb_build_object('name', 'after');", obj.toTypeReference(), obj) + assertNotNull(objUpdated) assertEquals(UUID.fromString("1e5f5d41-6d14-4007-897b-0ed2616bec96"), objUpdated.id) assertEquals("after", objUpdated.name) } @@ -110,8 +122,8 @@ class ConnectionTest : TestAbstract() { @Test fun `select one with named parameters`() { - val result: ObjTest3? = connection.selectOne( - "SELECT json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int)", + val result: ObjTest3? = connection.execute( + "SELECT json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int)", mapOf( "first" to "ff", "second" to "sec", @@ -126,8 +138,8 @@ class ConnectionTest : TestAbstract() { @Test fun `select one with named parameters object`() { - val result: ObjTestWithParameterObject? = connection.selectOne( - "SELECT json_build_object('first', :first::json, 'second', :second::json)", + val result: ObjTestWithParameterObject? = connection.execute( + "SELECT json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::json, 'second', :second::json)", mapOf( "first" to ParameterObject("one"), "second" to ParameterObject("two") @@ -140,11 +152,11 @@ class ConnectionTest : TestAbstract() { @Test fun `select with named parameters`() { - val result: List = connection.select( + val result: List? = connection.execute( """ SELECT json_build_array( - json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int), - json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int) + json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int), + json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int) ) """.trimIndent(), mapOf( @@ -153,6 +165,7 @@ class ConnectionTest : TestAbstract() { "second" to "sec" ) ) + assertNotNull(result) assertEquals("ff", result[0].first) assertEquals("sec", result[0].second) assertEquals(123, result[0].third) @@ -160,179 +173,33 @@ class ConnectionTest : TestAbstract() { @Test fun `select with named parameters as vararg of Pair`() { - val result: List = connection.select( + val result: List? = connection.execute( """ SELECT json_build_array( - json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int), - json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int) + json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int), + json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int) ) """.trimIndent(), "first" to "ff", "third" to 123, "second" to "sec" ) + assertNotNull(result) assertEquals("ff", result[0].first) assertEquals("sec", result[0].second) assertEquals(123, result[0].third) } @Test - fun `select paginated`() { - val result: Paginated = connection.select( - """ - SELECT json_build_array( - json_build_object('id', '417aaa7e-7bc6-49b7-9fe8-6c8433b3f430', 'name', :name::text), - json_build_object('id', 'abd46e7a-e749-4ce4-8361-e7b64da89da6', 'name', :name::text || '-2') - ), 10 as total - LIMIT :limit OFFSET :offset - """.trimIndent(), - 1, - 2, - mapOf("name" to "ff") - - ) - assertNotNull(result) - assertEquals("ff", result.result[0].name) - assertEquals("ff-2", result.result[1].name) - assertEquals(10, result.total) - assertEquals(0, result.offset) - } - - @Test - fun `test select paginated without result`() { - val result: Paginated = connection.select( - """ - SELECT null, - 10 as total - LIMIT :limit - OFFSET :offset - """.trimIndent(), - 1, - 2, - object : TypeReference>() {} - ) - assertNotNull(result) - assertTrue(result.result.isEmpty()) - assertEquals(0, result.result.size) - assertEquals(10, result.total) - assertEquals(0, result.offset) - } - - @Test - fun `test select paginated`() { - val result: Paginated = connection.select( - """ - SELECT json_build_array( - jsonb_build_object( - 'name', :name::text, - 'id', 'e9f9a0f0-237c-47cf-98c5-be353f2f2ce3' - ) - ), - 10 as total - LIMIT :limit - OFFSET :offset - """.trimIndent(), - 1, - 2, - object : TypeReference>() {}, - mapOf( - "name" to "myName" - ) - ) - assertNotNull(result) - assertEquals("myName", result.result[0].name) - assertEquals(1, result.result.size) - assertEquals(10, result.total) - assertEquals(0, result.offset) - } - - @Test - fun `test select paginated with no result`() { - assertThrows { - connection.select( - """ - SELECT :name as name, - 10 as total - LIMIT :limit - OFFSET :offset - """.trimIndent(), - 100, - 10, - object : TypeReference>() {}, - mapOf( - "name" to "myName" - ) - ) - }.run { - assertNotNull(message) - assertContains(message!!, "The query has no return") - } - } - - @Test - fun `test select paginated with total was not integer`() { - assertThrows { - connection.select( - """ - SELECT :name as name, - 'plop' as total - LIMIT :limit - OFFSET :offset - """.trimIndent(), - 1, - 10, - object : TypeReference>() {}, - mapOf( - "name" to "myName" - ) - ) - }.run { - assertNotNull(message) - assertContains(message!!, """Column "total" must be an integer""") - } - } - - @Test - fun `test select paginated without total`() { - val exception = assertThrows { - val result: Paginated = connection.select( - """ - SELECT null - LIMIT :limit - OFFSET :offset - """.trimIndent(), - 1, - 2, - object : TypeReference>() {} - ) - } - - assertEquals( - """ - The query not return the "total" column - - > :offset = 0, :limit = 2 - > SELECT null - > LIMIT :limit - > OFFSET :offset - > ----- - > ?column? - > null - """.trimIndent(), - exception.message - ) - } - - @Test - fun `selectOne with extra parameters`() { + fun `execute with extra parameters`() { val params: Map = mapOf( "first" to "ff", "third" to 123, "second" to "sec" ) - val result: ObjTest3? = connection.selectOne( + val result: ObjTest3? = connection.execute( """ - SELECT json_build_object('first', :first::text, 'second', :second::text, 'third', :third::int), 'plop'::text as other + SELECT json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::text, 'second', :second::text, 'third', :third::int), 'plop'::text as other """.trimIndent(), params ) { @@ -365,8 +232,8 @@ class ConnectionTest : TestAbstract() { @Test fun `select one in transaction`() { connection.inTransaction { - selectOne( - "SELECT json_build_object('first', :first::json, 'second', :second::json)", + execute( + "SELECT json_build_object('id', 'bf0e5605-3a8f-4db9-8b98-c8e0691dd576', 'first', :first::json, 'second', :second::json)", mapOf( "first" to ParameterObject("one"), "second" to ParameterObject("two") diff --git a/src/test/kotlin/fr/postgresjson/EntityTest.kt b/src/test/kotlin/fr/postgresjson/EntityTest.kt deleted file mode 100644 index 1111f8d..0000000 --- a/src/test/kotlin/fr/postgresjson/EntityTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package fr.postgresjson - -import fr.postgresjson.entity.Entity -import fr.postgresjson.entity.EntityCreatedAt -import fr.postgresjson.entity.EntityCreatedBy -import fr.postgresjson.entity.EntityI -import fr.postgresjson.entity.EntityUpdatedAt -import fr.postgresjson.entity.EntityUpdatedBy -import fr.postgresjson.entity.Published -import fr.postgresjson.entity.UuidEntityExtended -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.TestInstance -import java.util.UUID - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -class EntityTest() { - private class User(id: UUID = UUID.randomUUID()) : Entity(id) - private class ObjTest(val name: String) : UuidEntityExtended(User(), User()) - - @Test - fun getObject() { - val obj = ObjTest("plop") - assertTrue(obj is ObjTest) - assertTrue(obj is UuidEntityExtended) - assertTrue(obj is EntityI) - assertTrue(obj is Entity) - assertTrue(obj is Published) - assertTrue(obj is EntityCreatedBy) - assertTrue(obj is EntityUpdatedBy) - assertTrue(obj is EntityCreatedAt) - assertTrue(obj is EntityUpdatedAt) - } -} diff --git a/src/test/kotlin/fr/postgresjson/MigrationTest.kt b/src/test/kotlin/fr/postgresjson/MigrationTest.kt index 822c3f0..6fac4fb 100644 --- a/src/test/kotlin/fr/postgresjson/MigrationTest.kt +++ b/src/test/kotlin/fr/postgresjson/MigrationTest.kt @@ -1,7 +1,7 @@ package fr.postgresjson import fr.postgresjson.connexion.Requester -import fr.postgresjson.connexion.selectOne +import fr.postgresjson.connexion.execute import fr.postgresjson.migration.Migration import fr.postgresjson.migration.Migrations import org.amshove.kluent.invoking @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test import org.junit.jupiter.api.TestInstance import java.util.UUID +import kotlin.test.assertEquals +import kotlin.test.assertNotNull @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MigrationTest : TestAbstract() { @@ -83,12 +85,12 @@ class MigrationTest : TestAbstract() { val resourcesFunctions = this::class.java.getResource("/sql/function/Test")!!.toURI() Migrations(listOf(resources, resourcesFunctions), connection).apply { up().apply { - size `should be equal to` 7 + size `should be equal to` 6 } } Migrations(listOf(resources, resourcesFunctions), connection).apply { forceAllDown().apply { - size `should be equal to` 7 + size `should be equal to` 6 } } } @@ -97,15 +99,16 @@ class MigrationTest : TestAbstract() { fun `run functions migrations`() { val resources = this::class.java.getResource("/sql/function/Test")!!.toURI() Migrations(resources, connection).apply { - run().size `should be equal to` 6 + run().size `should be equal to` 5 } val objTest: RequesterTest.ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function") - .selectOne(listOf("test", "plip")) + .execute(listOf("test", "plip")) - Assertions.assertEquals(objTest!!.id, UUID.fromString("457daad5-4f1b-4eb7-80ec-6882adb8cc7d")) - Assertions.assertEquals(objTest.name, "test") + assertNotNull(objTest) + assertEquals(objTest.id, UUID.fromString("457daad5-4f1b-4eb7-80ec-6882adb8cc7d")) + assertEquals(objTest.name, "test") } @Test @@ -117,7 +120,7 @@ class MigrationTest : TestAbstract() { val objTest: RequesterTest.ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function_duplicate") - .selectOne(listOf("test")) + .execute(listOf("test")) Assertions.assertEquals(objTest!!.id, UUID.fromString("457daad5-4f1b-4eb7-80ec-6882adb8cc7d")) Assertions.assertEquals(objTest.name, "test") diff --git a/src/test/kotlin/fr/postgresjson/RequesterTest.kt b/src/test/kotlin/fr/postgresjson/RequesterTest.kt index 997939f..47eaa3b 100644 --- a/src/test/kotlin/fr/postgresjson/RequesterTest.kt +++ b/src/test/kotlin/fr/postgresjson/RequesterTest.kt @@ -2,14 +2,11 @@ package fr.postgresjson import com.fasterxml.jackson.core.type.TypeReference import fr.postgresjson.connexion.Connection.QueryError -import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester import fr.postgresjson.connexion.Requester.NoFunctionDefined import fr.postgresjson.connexion.Requester.NoQueryDefined -import fr.postgresjson.connexion.select -import fr.postgresjson.connexion.selectOne -import fr.postgresjson.connexion.update -import fr.postgresjson.entity.UuidEntity +import fr.postgresjson.connexion.SqlSerializable +import fr.postgresjson.connexion.execute import fr.postgresjson.serializer.deserialize import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Test @@ -18,7 +15,8 @@ import kotlin.test.assertEquals import kotlin.test.assertNotNull class RequesterTest : TestAbstract() { - class ObjTest(val name: String, id: UUID = UUID.fromString("5623d902-3067-42f3-bfd9-095dbb12c29f")) : UuidEntity(id) + @SqlSerializable + class ObjTest(val name: String, val id: UUID = UUID.fromString("5623d902-3067-42f3-bfd9-095dbb12c29f")) @Test fun `requester constructor empty`() { @@ -99,7 +97,7 @@ class RequesterTest : TestAbstract() { val objTest: ObjTest? = Requester(connection) .apply { addQuery(resources) } .getQuery("selectOne") - .selectOne() + .execute() assertNotNull(objTest) assertEquals(objTest.id, UUID.fromString("829b1a29-5db8-47f9-9562-961c561ac528")) @@ -138,7 +136,7 @@ class RequesterTest : TestAbstract() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val objTest: ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function") - .selectOne(listOf("test", "plip")) + .execute(listOf("test", "plip")) assertNotNull(objTest) assertEquals(objTest.id, UUID.fromString("457daad5-4f1b-4eb7-80ec-6882adb8cc7d")) @@ -162,7 +160,7 @@ class RequesterTest : TestAbstract() { .getQuery("selectOneWithParameters") .exec(listOf("myName")) - assertEquals("myName", result.rows[0].getString(0)?.deserialize()?.name) + assertEquals("myName", result.deserialize()?.name) } @Test @@ -285,23 +283,23 @@ class RequesterTest : TestAbstract() { } @Test - fun `call selectOne on function`() { + fun `call execute on function`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val obj: ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function") - .selectOne(mapOf("name" to "myName")) + .execute(mapOf("name" to "myName")) assertNotNull(obj) assertEquals("myName", obj.name) } @Test - fun `call selectOne on function with object and named argument`() { + fun `call execute on function with object and named argument`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val obj2 = ObjTest("original") val obj: ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function_object") - .selectOne("resource" to obj2) + .execute("resource" to obj2) assertNotNull(obj) assertEquals("changedName", obj.name) @@ -309,12 +307,12 @@ class RequesterTest : TestAbstract() { } @Test - fun `call selectOne on function with object`() { + fun `call execute on function with object`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val obj2 = ObjTest("original") val obj: ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function_object") - .update(obj2) + .execute(listOf(obj2)) assertNotNull(obj) assertEquals("changedName", obj.name) @@ -322,22 +320,22 @@ class RequesterTest : TestAbstract() { } @Test - fun `call selectOne on function with object and no arguments`() { + fun `call execute on function with object and no arguments`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() val obj: ObjTest? = Requester(connection, functionsDirectory = resources) .getFunction("test_function") - .selectOne() + .execute() assertNotNull(obj) assertEquals("plop", obj.name) } @Test - fun `call selectOne on query`() { + fun `call execute on query`() { val resources = this::class.java.getResource("/sql/query")?.toURI() val obj: ObjTest? = Requester(connection, queriesDirectory = resources) .getQuery("selectOneWithParameters") - .selectOne(mapOf("name" to "myName")) + .execute(mapOf("name" to "myName")) assertNotNull(obj) assertEquals("myName", obj.name) @@ -346,10 +344,11 @@ class RequesterTest : TestAbstract() { @Test fun `call select (multiple) on function with named argument`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() - val obj: List = Requester(connection, functionsDirectory = resources) + val obj: List? = Requester(connection, functionsDirectory = resources) .getFunction("test_function_multiple") - .select(mapOf("name" to "myName")) + .execute(mapOf("name" to "myName")) + assertNotNull(obj) assertNotNull(obj[0]) assertEquals("myName", obj[0].name) assertEquals("myName", obj[0].name) @@ -358,10 +357,11 @@ class RequesterTest : TestAbstract() { @Test fun `call select (multiple) on function with ordered arguments`() { val resources = this::class.java.getResource("/sql/function/Test")?.toURI() - val obj: List = Requester(connection, functionsDirectory = resources) + val obj: List? = Requester(connection, functionsDirectory = resources) .getFunction("test_function_multiple") - .select(listOf("myName")) + .execute(listOf("myName")) + assertNotNull(obj) assertEquals("myName", obj[0].name) } @@ -370,13 +370,13 @@ class RequesterTest : TestAbstract() { val resources = this::class.java.getResource("/sql/query")?.toURI() Requester(connection, queriesDirectory = resources) .getQuery("selectMultiple").apply { - select(mapOf("name" to "ff")).let { result -> + execute>(mapOf("name" to "ff")).let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("ff-2", result[1].name) } }.apply { - select(object : TypeReference>() {}, mapOf("name" to "ff")).let { result -> + execute(object : TypeReference>() {}, mapOf("name" to "ff")).let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("ff-2", result[1].name) @@ -389,13 +389,13 @@ class RequesterTest : TestAbstract() { val resources = this::class.java.getResource("/sql/query")?.toURI() Requester(connection, queriesDirectory = resources) .getQuery("selectMultiple").apply { - select("name" to "ff").let { result -> + execute>("name" to "ff").let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("ff-2", result[1].name) } }.apply { - select(object : TypeReference>() {}, "name" to "ff").let { result -> + execute(object : TypeReference>() {}, "name" to "ff").let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("ff-2", result[1].name) @@ -408,13 +408,13 @@ class RequesterTest : TestAbstract() { val resources = this::class.java.getResource("/sql/query")?.toURI() Requester(connection, queriesDirectory = resources) .getQuery("selectMultipleOrderedArgs").apply { - select(listOf("ff", "aa")).let { result -> + execute>(listOf("ff", "aa")).let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("aa-2", result[1].name) } }.apply { - select(object : TypeReference>() {}, listOf("ff", "aa")).let { result -> + execute(object : TypeReference>() {}, listOf("ff", "aa")).let { result -> assertNotNull(result) assertEquals("ff", result[0].name) assertEquals("aa-2", result[1].name) @@ -423,71 +423,11 @@ class RequesterTest : TestAbstract() { } @Test - fun `call select paginated on query`() { - val resources = this::class.java.getResource("/sql/query")?.toURI() - val result: Paginated = Requester(connection, queriesDirectory = resources) - .getQuery("selectPaginated") - .select(1, 2, mapOf("name" to "ff")) - assertNotNull(result) - assertEquals("ff", result.result[0].name) - assertEquals("ff-2", result.result[1].name) - assertEquals(10, result.total) - assertEquals(0, result.offset) - } - - @Test - fun `call select paginated on function`() { - val resources = this::class.java.getResource("/sql/function")?.toURI() - Requester(connection, functionsDirectory = resources) - .getFunction("test_function_paginated").apply { - select(1, 2, mapOf("name" to "ff")).run { - assertNotNull(result) - assertEquals("ff", result[0].name) - assertEquals("ff-2", result[1].name) - assertEquals(10, total) - assertEquals(0, offset) - } - }.apply { - select(1, 2, object : TypeReference>() {}, mapOf("name" to "ff")).run { - assertNotNull(result) - assertEquals("ff", result[0].name) - assertEquals("ff-2", result[1].name) - assertEquals(10, total) - assertEquals(0, offset) - } - } - } - - @Test - fun `call select paginated on function with vararg`() { - val resources = this::class.java.getResource("/sql/function")?.toURI() - Requester(connection, functionsDirectory = resources) - .getFunction("test_function_paginated") - .select(1, 2, "name" to "ff").run { - assertNotNull(result) - assertEquals("ff", result[0].name) - assertEquals("ff-2", result[1].name) - assertEquals(10, total) - assertEquals(0, offset) - } - - Requester(connection, functionsDirectory = resources) - .getFunction("test_function_paginated") - .select(1, 2, object : TypeReference>() {}, "name" to "ff").run { - assertNotNull(result) - assertEquals("ff", result[0].name) - assertEquals("ff-2", result[1].name) - assertEquals(10, total) - assertEquals(0, offset) - } - } - - @Test - fun `call selectOne on query with extra parameter`() { + fun `call execute on query with extra parameter`() { val resources = this::class.java.getResource("/sql/query")?.toURI() Requester(connection, queriesDirectory = resources) .getQuery("selectOneWithParameters").apply { - selectOne(mapOf("name" to "myName")) { + execute(mapOf("name" to "myName")) { assertNotNull(it) assertEquals("myName", it.name) assertEquals("plop", rows[0].getString("other")) @@ -495,7 +435,7 @@ class RequesterTest : TestAbstract() { assertEquals("selectOneWithParameters", name) } }.apply { - selectOne(typeReference = object : TypeReference() {}, values = mapOf("name" to "myName")) { + execute(typeReference = object : TypeReference() {}, values = mapOf("name" to "myName")) { assertNotNull(it) assertEquals("myName", it.name) assertEquals("plop", rows[0].getString("other")) diff --git a/src/test/kotlin/fr/postgresjson/SerializerTest.kt b/src/test/kotlin/fr/postgresjson/SerializerTest.kt index b8d7b3a..047e289 100644 --- a/src/test/kotlin/fr/postgresjson/SerializerTest.kt +++ b/src/test/kotlin/fr/postgresjson/SerializerTest.kt @@ -1,8 +1,6 @@ package fr.postgresjson -import fr.postgresjson.entity.UuidEntity import fr.postgresjson.serializer.Serializer -import fr.postgresjson.serializer.serialize import org.joda.time.DateTime import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue @@ -13,8 +11,8 @@ import java.util.UUID @TestInstance(TestInstance.Lifecycle.PER_CLASS) internal class SerializerTest { - private class ObjTest(var val1: String, var val2: Int, id: UUID = UUID.fromString("1e5f5d41-6d14-4007-897b-0ed2616bec96")) : UuidEntity(id) - private class ObjTestDate(var val1: DateTime, id: UUID = UUID.fromString("829b1a29-5db8-47f9-9562-961c561ac528")) : UuidEntity(id) + private class ObjTest(var val1: String, var val2: Int,val id: UUID = UUID.fromString("1e5f5d41-6d14-4007-897b-0ed2616bec96")) + private class ObjTestDate(var val1: DateTime, val id: UUID = UUID.fromString("829b1a29-5db8-47f9-9562-961c561ac528")) private val serializer = Serializer() @@ -33,16 +31,10 @@ internal class SerializerTest { assertTrue(json.contains(""""val1":"plop","val2":123""")) } - @Test - fun serialize2() { - val json = obj.serialize() - assertTrue(json.contains(""""val1":"plop","val2":123""")) - } - @Test fun serializeList() { val list = listOf(ObjTest("one", 1), ObjTest("two", 2)) - val json = list.serialize() + val json = serializer.serialize(list) assertTrue(json.contains(""""val1":"one","val2":1""")) assertTrue(json.contains(""""val1":"two","val2":2""")) } @@ -50,7 +42,7 @@ internal class SerializerTest { @Test fun serializeDate() { val objDate = ObjTestDate(DateTime.parse("2019-07-30T14:08:51.420108+04:00")) - val json = objDate.serialize() + val json = serializer.serialize(objDate) assertTrue(json.contains(""""val1":"2019-07-30T10:08:51.420Z""""), json) } diff --git a/src/test/kotlin/fr/postgresjson/functionGenerator/FunctionGeneratorTest.kt b/src/test/kotlin/fr/postgresjson/functionGenerator/FunctionGeneratorTest.kt index 518d42e..712bab0 100644 --- a/src/test/kotlin/fr/postgresjson/functionGenerator/FunctionGeneratorTest.kt +++ b/src/test/kotlin/fr/postgresjson/functionGenerator/FunctionGeneratorTest.kt @@ -27,11 +27,10 @@ class FunctionGeneratorTest : StringSpec({ | |import com.fasterxml.jackson.core.type.TypeReference |import fr.postgresjson.connexion.Requester - |import fr.postgresjson.entity.Serializable | - |inline fun Requester.testFunctionObject(resource: S): E { + |inline fun Requester.testFunctionObject(resource: S): E? { | return getFunction("test_function_object") - | .selectAny(object : TypeReference() {}, mapOf("resource" to resource)) + | .execute(object : TypeReference() {}, mapOf("resource" to resource)) |} """.trimMargin() @@ -85,9 +84,9 @@ class FunctionGeneratorTest : StringSpec({ |import com.fasterxml.jackson.core.type.TypeReference |import fr.postgresjson.connexion.Requester | - |inline fun Requester.testFunctionMultiple(name: String = "plop", hi: String = "hello"): E { + |inline fun Requester.testFunctionMultiple(name: String = "plop", hi: String = "hello"): E? { | return getFunction("test_function_multiple") - | .selectAny(object : TypeReference() {}, mapOf("name" to name, "hi" to hi)) + | .execute(object : TypeReference() {}, mapOf("name" to name, "hi" to hi)) |} """.trimMargin() diff --git a/src/test/resources/sql/function/Test/test_function_paginated.sql b/src/test/resources/sql/function/Test/test_function_paginated.sql deleted file mode 100644 index d10b6fc..0000000 --- a/src/test/resources/sql/function/Test/test_function_paginated.sql +++ /dev/null @@ -1,21 +0,0 @@ -create or replace function test_function_paginated( - name text default 'plop', - in "limit" int default 10, - in "offset" int default 0, - out result json, - out total int -) - language plpgsql -as -$$ -begin - select - json_build_array( - json_build_object('id', '457daad5-4f1b-4eb7-80ec-6882adb8cc7d', 'name', name::text), - json_build_object('id', '8d20abb0-7f77-4b6c-9991-44acd3c88faa', 'name', name::text || '-2') - ), - 10 - into result, total - limit "limit" offset "offset"; -end; -$$ \ No newline at end of file