diff --git a/build.gradle.kts b/build.gradle.kts index 6f37a7e..98d00dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,8 +18,8 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-reflect:1.3.31") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.9") implementation("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.9") - implementation("com.github.jasync-sql:jasync-postgresql:0.9.53") implementation("org.slf4j:slf4j-api:1.7.26") + implementation("org.postgresql:postgresql:42.2.6") testImplementation("ch.qos.logback:logback-classic:1.2.3") testImplementation("ch.qos.logback:logback-core:1.2.3") @@ -32,7 +32,7 @@ publishing { publications { create("maven") { groupId = "fr.postgresjson" - artifactId = "postgresjson" + artifactId = "postgresjson-jdbc" version = "0.1" from(components["java"]) diff --git a/src/main/kotlin/fr/postgresjson/connexion/Connection.kt b/src/main/kotlin/fr/postgresjson/connexion/Connection.kt index cb47567..0a067d1 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Connection.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Connection.kt @@ -1,20 +1,17 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.Connection -import com.github.jasync.sql.db.QueryResult -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 fr.postgresjson.entity.EntityI import fr.postgresjson.serializer.Serializer import fr.postgresjson.utils.LoggerDelegate import org.slf4j.Logger -import java.util.concurrent.CompletableFuture +import java.sql.DriverManager +import java.sql.ResultSet +import java.sql.Connection as JDBCConnection -typealias SelectOneCallback = QueryResult.(T?) -> Unit -typealias SelectCallback = QueryResult.(List) -> Unit -typealias SelectPaginatedCallback = QueryResult.(Paginated) -> Unit +typealias SelectOneCallback = ResultSet.(T?) -> Unit +typealias SelectCallback = ResultSet.(List) -> Unit +typealias SelectPaginatedCallback = ResultSet.(Paginated) -> Unit class Connection( private val database: String, @@ -23,32 +20,34 @@ class Connection( private val host: String = "localhost", private val port: Int = 5432 ): Executable { - private lateinit var connection: ConnectionPool + private lateinit var connection: JDBCConnection private val serializer = Serializer() private val logger: Logger? by LoggerDelegate() - internal fun connect(): ConnectionPool { - if (!::connection.isInitialized || !connection.isConnected()) { - connection = PostgreSQLConnectionBuilder.createConnectionPool( - "jdbc:postgresql://$host:$port/$database?user=$username&password=$password" - ) + internal fun connect(): JDBCConnection { + if (!::connection.isInitialized || connection.isClosed) { + connection = DriverManager.getConnection("jdbc:postgresql://$host:$port/$database", username, password) } return connection } - fun inTransaction(f: (Connection) -> CompletableFuture) = connect().inTransaction(f) + fun inTransaction(f: (Connection) -> T) { + sendQuery("BEGIN") + f(this) + sendQuery("COMMIT") + } override fun > select( sql: String, typeReference: TypeReference, values: List, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { val primaryObject = values.firstOrNull { it is EntityI<*> && typeReference.type.typeName == it::class.java.name } as R? val result = exec(sql, compileArgs(values)) - val json = result.rows[0].getString(0) + val json = result.getString(1) return if (json === null) { null } else { @@ -73,7 +72,7 @@ class Connection( sql: String, typeReference: TypeReference, values: Map, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { return replaceArgs(sql, values) { select(this.sql, typeReference, this.parameters, block) @@ -91,10 +90,10 @@ class Connection( sql: String, typeReference: TypeReference>, values: List, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { val result = exec(sql, compileArgs(values)) - val json = result.rows[0].getString(0) + val json = result.getString(1) return if (json === null) { listOf>() as List } else { @@ -117,7 +116,7 @@ class Connection( limit: Int, typeReference: TypeReference>, values: Map, - block: (QueryResult, Paginated) -> Unit + block: (ResultSet, Paginated) -> Unit ): Paginated { val offset = (page - 1) * limit val newValues = values @@ -125,11 +124,11 @@ class Connection( .plus("limit" to limit) val line = replaceArgs(sql, newValues) { - exec(this.sql, compileArgs(this.parameters)) + exec(this.sql, this.parameters) } return line.run { - val json = rows[0].getString(0) + val json = getString(1) val entities = if (json === null) { listOf>() as List } else { @@ -139,7 +138,7 @@ class Connection( entities, offset, limit, - rows[0].getInt("total") ?: error("The query not return total") + getInt("total") ) }.also { block(line, it) @@ -159,7 +158,7 @@ class Connection( sql: String, typeReference: TypeReference>, values: Map, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { return replaceArgs(sql, values) { select(this.sql, typeReference, this.parameters, block) @@ -173,21 +172,37 @@ class Connection( ): List = select(sql, object: TypeReference>() {}, values, block) - override fun exec(sql: String, values: List): QueryResult { + override fun exec(sql: String, values: List): ResultSet { return stopwatchQuery(sql, values) { - connect().sendPreparedStatement(sql, compileArgs(values)).join() + connect().prepareStatement(sql).apply { + compileArgs(values).forEachIndexed { i, v -> + when (v) { + is String -> setString(i+1, v) + is Int -> setInt(i+1, v) + else -> setString(i+1, v.toString()) + } + } + }.executeQuery().apply { next() } } } - override fun exec(sql: String, values: Map): QueryResult { + override fun exec(sql: String, values: Map): ResultSet { return replaceArgs(sql, values) { exec(this.sql, this.parameters) } } - override fun sendQuery(sql: String): QueryResult { - return stopwatchQuery(sql) { - connect().sendQuery(sql).join() + override fun sendQuery(sql: String, values: List): Int { + return stopwatchQuery(sql, values) { + connect().prepareStatement(sql).apply { + compileArgs(values).forEachIndexed { i, v -> + when (v) { + is String -> setString(i+1, v) + is Int -> setInt(i+1, v) + else -> setString(i+1, v.toString()) + } + } + }.executeUpdate() } } diff --git a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt index 59437c8..7a22d82 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/EmbedExecutable.kt @@ -1,8 +1,8 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.QueryResult import fr.postgresjson.entity.EntityI +import java.sql.ResultSet interface EmbedExecutable { val connection: Connection @@ -47,6 +47,6 @@ interface EmbedExecutable { block: SelectPaginatedCallback = {} ): Paginated - fun exec(values: List = emptyList()): QueryResult - fun exec(values: Map): QueryResult + fun exec(values: List = emptyList()): ResultSet + fun exec(values: Map): ResultSet } \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/connexion/Executable.kt b/src/main/kotlin/fr/postgresjson/connexion/Executable.kt index 08daedd..fefac71 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Executable.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Executable.kt @@ -1,8 +1,8 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.QueryResult import fr.postgresjson.entity.EntityI +import java.sql.ResultSet interface Executable { /* Select One */ @@ -48,7 +48,7 @@ interface Executable { block: SelectPaginatedCallback = {} ): Paginated - fun exec(sql: String, values: List = emptyList()): QueryResult - fun exec(sql: String, values: Map): QueryResult - fun sendQuery(sql: String): QueryResult + fun exec(sql: String, values: List = emptyList()): ResultSet + fun exec(sql: String, values: Map): ResultSet + fun sendQuery(sql: String, values: List = emptyList()): Int } \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/connexion/Function.kt b/src/main/kotlin/fr/postgresjson/connexion/Function.kt index 4d42538..fab6597 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Function.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Function.kt @@ -1,9 +1,9 @@ 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 +import java.sql.ResultSet class Function(val definition: Function, override val connection: Connection): EmbedExecutable { override fun toString(): String { @@ -20,7 +20,7 @@ class Function(val definition: Function, override val connection: Connection): E override fun > select( typeReference: TypeReference, values: List, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" @@ -46,7 +46,7 @@ class Function(val definition: Function, override val connection: Connection): E override fun > select( typeReference: TypeReference, values: Map, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" @@ -74,7 +74,7 @@ class Function(val definition: Function, override val connection: Connection): E override fun > select( typeReference: TypeReference>, values: List, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" @@ -94,7 +94,7 @@ class Function(val definition: Function, override val connection: Connection): E override fun > select( typeReference: TypeReference>, values: Map, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" @@ -124,7 +124,7 @@ class Function(val definition: Function, override val connection: Connection): E limit: Int, typeReference: TypeReference>, values: Map, - block: (QueryResult, Paginated) -> Unit + block: (ResultSet, Paginated) -> Unit ): Paginated { val offset = (page - 1) * limit val newValues = values @@ -155,14 +155,14 @@ class Function(val definition: Function, override val connection: Connection): E /* Execute function without traitements */ - override fun exec(values: List): QueryResult { + override fun exec(values: List): ResultSet { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" return connection.exec(sql, values) } - override fun exec(values: Map): QueryResult { + override fun exec(values: Map): ResultSet { val args = compileArgs(values) val sql = "SELECT * FROM ${definition.name} ($args)" diff --git a/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt b/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt index cb6d21f..9b00544 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Paginated.kt @@ -1,6 +1,5 @@ package fr.postgresjson.connexion -import com.github.jasync.sql.db.util.length import fr.postgresjson.entity.EntityI data class Paginated>( @@ -10,7 +9,7 @@ data class Paginated>( val total: Int ) { val currentPage: Int = (offset / limit) + 1 - val count: Int = result.length + val count: Int = result.size init { if (offset < 0) error("offset must be greather or equal than 0") diff --git a/src/main/kotlin/fr/postgresjson/connexion/Query.kt b/src/main/kotlin/fr/postgresjson/connexion/Query.kt index 5bdce80..5dff06a 100644 --- a/src/main/kotlin/fr/postgresjson/connexion/Query.kt +++ b/src/main/kotlin/fr/postgresjson/connexion/Query.kt @@ -1,8 +1,8 @@ package fr.postgresjson.connexion import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.QueryResult import fr.postgresjson.entity.EntityI +import java.sql.ResultSet class Query(override val name: String, private val sql: String, override val connection: Connection): EmbedExecutable { @@ -15,7 +15,7 @@ class Query(override val name: String, private val sql: String, override val con override fun > select( typeReference: TypeReference, values: List, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { return connection.select(this.toString(), typeReference, values, block) } @@ -29,7 +29,7 @@ class Query(override val name: String, private val sql: String, override val con override fun > select( typeReference: TypeReference, values: Map, - block: (QueryResult, R?) -> Unit + block: (ResultSet, R?) -> Unit ): R? { return connection.select(this.toString(), typeReference, values, block) } @@ -45,7 +45,7 @@ class Query(override val name: String, private val sql: String, override val con override fun > select( typeReference: TypeReference>, values: List, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { return connection.select(this.toString(), typeReference, values, block) } @@ -59,7 +59,7 @@ class Query(override val name: String, private val sql: String, override val con override fun > select( typeReference: TypeReference>, values: Map, - block: (QueryResult, List) -> Unit + block: (ResultSet, List) -> Unit ): List { return connection.select(this.toString(), typeReference, values, block) } @@ -75,7 +75,7 @@ class Query(override val name: String, private val sql: String, override val con limit: Int, typeReference: TypeReference>, values: Map, - block: (QueryResult, Paginated) -> Unit + block: (ResultSet, Paginated) -> Unit ): Paginated { return connection.select(this.toString(), page, limit, typeReference, values, block) } @@ -92,11 +92,11 @@ class Query(override val name: String, private val sql: String, override val con /* Execute function without traitements */ - override fun exec(values: List): QueryResult { + override fun exec(values: List): ResultSet { return connection.exec(sql, values) } - override fun exec(values: Map): QueryResult { + override fun exec(values: Map): ResultSet { return connection.exec(sql, values) } } \ No newline at end of file diff --git a/src/main/kotlin/fr/postgresjson/migration/Function.kt b/src/main/kotlin/fr/postgresjson/migration/Function.kt index 2078521..7023eed 100644 --- a/src/main/kotlin/fr/postgresjson/migration/Function.kt +++ b/src/main/kotlin/fr/postgresjson/migration/Function.kt @@ -59,7 +59,7 @@ data class Function( up() down() it.sendQuery("ROLLBACK") - }.join() + } return Status.OK // TODO } @@ -69,7 +69,7 @@ data class Function( up() down() it.sendQuery("ROLLBACK") - }.join() + } return Status.OK // TODO } diff --git a/src/main/kotlin/fr/postgresjson/migration/Migrations.kt b/src/main/kotlin/fr/postgresjson/migration/Migrations.kt index 87dfc69..76db617 100644 --- a/src/main/kotlin/fr/postgresjson/migration/Migrations.kt +++ b/src/main/kotlin/fr/postgresjson/migration/Migrations.kt @@ -1,7 +1,6 @@ package fr.postgresjson.migration import com.fasterxml.jackson.core.type.TypeReference -import com.github.jasync.sql.db.util.size import fr.postgresjson.connexion.Connection import fr.postgresjson.definition.Function.FunctionNotFound import fr.postgresjson.entity.Entity @@ -97,11 +96,11 @@ data class Migrations private constructor( it.isFile }.forEach { file -> if (file.name.endsWith(".up.sql")) { - file.path.substring(0, file.path.size - 7).let { + file.path.substring(0, file.path.length - 7).let { try { val down = File("$it.down.sql").readText() val up = file.readText() - val name = file.name.substring(0, file.name.size - 7) + val name = file.name.substring(0, file.name.length - 7) addQuery(name, up, down) } catch (e: FileNotFoundException) { throw DownMigrationNotDefined("$it.down.sql", e) diff --git a/src/main/kotlin/fr/postgresjson/migration/Query.kt b/src/main/kotlin/fr/postgresjson/migration/Query.kt index 673d994..040b0de 100644 --- a/src/main/kotlin/fr/postgresjson/migration/Query.kt +++ b/src/main/kotlin/fr/postgresjson/migration/Query.kt @@ -31,7 +31,7 @@ data class Query( connection.sendQuery(down) this::class.java.classLoader.getResource("sql/migration/deleteHistory.sql")!!.readText().let { - connection.exec(it, listOf(name)) + connection.sendQuery(it, listOf(name)) } return Migration.Status.OK @@ -42,7 +42,7 @@ data class Query( up() down() it.sendQuery("ROLLBACK") - }.join() + } return Migration.Status.OK // TODO } @@ -52,7 +52,7 @@ data class Query( up() down() it.sendQuery("ROLLBACK") - }.join() + } return Migration.Status.OK // TODO } diff --git a/src/test/kotlin/fr/postgresjson/ConnectionTest.kt b/src/test/kotlin/fr/postgresjson/ConnectionTest.kt index e07fdbb..232b568 100644 --- a/src/test/kotlin/fr/postgresjson/ConnectionTest.kt +++ b/src/test/kotlin/fr/postgresjson/ConnectionTest.kt @@ -72,7 +72,7 @@ class ConnectionTest(): TestAbstract() { fun callExec() { val o = ObjTest("myName") val result = connection.exec("select json_build_object('id', 1, 'name', ?::json->>'name')", listOf(o)) - Assertions.assertEquals(1, result.rowsAffected) + Assertions.assertNotNull(result.getString(1)) } @Test @@ -166,7 +166,7 @@ class ConnectionTest(): TestAbstract() { params ) { assertEquals("ff", it!!.first) - assertEquals("plop", rows[0].getString("other")) + assertEquals("plop", getString("other")) } assertNotNull(result) assertEquals("ff", result!!.first) diff --git a/src/test/kotlin/fr/postgresjson/RequesterTest.kt b/src/test/kotlin/fr/postgresjson/RequesterTest.kt index 050647f..f4d58ea 100644 --- a/src/test/kotlin/fr/postgresjson/RequesterTest.kt +++ b/src/test/kotlin/fr/postgresjson/RequesterTest.kt @@ -4,6 +4,7 @@ import fr.postgresjson.connexion.Paginated import fr.postgresjson.connexion.Requester import fr.postgresjson.entity.IdEntity import org.junit.Assert +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import java.io.File @@ -43,7 +44,7 @@ class RequesterTest: TestAbstract() { .getQuery("Test/selectOne") .exec() - assertEquals(1, result.rowsAffected) + Assertions.assertNotNull(result.getString(1)) } @Test @@ -54,7 +55,7 @@ class RequesterTest: TestAbstract() { .getFunction("test_function") .exec(listOf("test", "plip")) - assertEquals(1, result.rowsAffected) + Assertions.assertNotNull(result.getString(1)) } @Test @@ -139,7 +140,7 @@ class RequesterTest: TestAbstract() { .getQuery("Test/selectOneWithParameters") .selectOne(mapOf("name" to "myName")) { assertEquals("myName", it!!.name) - Assert.assertEquals("plop", rows[0].getString("other")) + Assert.assertEquals("plop", getString("other")) }!! assertEquals("myName", obj.name) diff --git a/src/test/kotlin/fr/postgresjson/TestAbstract.kt b/src/test/kotlin/fr/postgresjson/TestAbstract.kt index 7120a09..96394d2 100644 --- a/src/test/kotlin/fr/postgresjson/TestAbstract.kt +++ b/src/test/kotlin/fr/postgresjson/TestAbstract.kt @@ -9,20 +9,22 @@ import java.io.File @TestInstance(PER_CLASS) abstract class TestAbstract { + private var connection = Connection(database = "test", username = "test", password = "test") + protected fun getConnextion(): Connection { - return Connection(database = "test", username = "test", password = "test") + return connection } @BeforeEach fun beforeAll() { val initSQL = File(this::class.java.getResource("/fixtures/init.sql").toURI()) - val promise = getConnextion().connect().sendQuery(initSQL.readText()) - promise.join() + getConnextion().connect().createStatement().executeUpdate(initSQL.readText()) } @AfterEach fun afterAll() { val downSQL = File(this::class.java.getResource("/fixtures/down.sql").toURI()) - getConnextion().connect().sendQuery(downSQL.readText()).join() + getConnextion().connect().createStatement().executeUpdate(downSQL.readText()) + getConnextion().connect().close() } } \ No newline at end of file diff --git a/src/test/resources/sql/migration_without_down/1.up.sql b/src/test/resources/sql/migration_without_down/1.up.sql index 027b7d6..89ac949 100644 --- a/src/test/resources/sql/migration_without_down/1.up.sql +++ b/src/test/resources/sql/migration_without_down/1.up.sql @@ -1 +1,5 @@ -SELECT 1; \ No newline at end of file +do $$ + begin + PERFORM 1; + end; +$$ diff --git a/src/test/resources/sql/migrations/1.down.sql b/src/test/resources/sql/migrations/1.down.sql index 027b7d6..1274bc7 100644 --- a/src/test/resources/sql/migrations/1.down.sql +++ b/src/test/resources/sql/migrations/1.down.sql @@ -1 +1,5 @@ -SELECT 1; \ No newline at end of file +do $$ + begin + PERFORM 1; + end; +$$ \ No newline at end of file diff --git a/src/test/resources/sql/migrations/1.up.sql b/src/test/resources/sql/migrations/1.up.sql index 027b7d6..1274bc7 100644 --- a/src/test/resources/sql/migrations/1.up.sql +++ b/src/test/resources/sql/migrations/1.up.sql @@ -1 +1,5 @@ -SELECT 1; \ No newline at end of file +do $$ + begin + PERFORM 1; + end; +$$ \ No newline at end of file