com.vladsch.kotlin.jdbc.SessionImpl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-jdbc Show documentation
Show all versions of kotlin-jdbc Show documentation
A thin library that exposes JDBC API with the convenience of Kotlin and gets out of the way when not needed.
The newest version!
package com.vladsch.kotlin.jdbc
import com.vladsch.boxed.json.MutableJsArray
import com.vladsch.boxed.json.MutableJsObject
import org.slf4j.LoggerFactory
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.Statement
import javax.json.JsonArray
import javax.json.JsonObject
import javax.sql.DataSource
open class SessionImpl(
override val connection: Connection,
override val autoGeneratedKeys: List = listOf()
) : Session {
override val identifierQuoteString: String
get() = connection.underlying.metaData.identifierQuoteString
companion object {
private val logger = LoggerFactory.getLogger(Session::class.java)
var defaultDataSource: (() -> DataSource)? = null
}
override fun close() {
connection.close()
}
override fun use(block: (Session) -> Unit) {
this.use {
block.invoke(this)
}
}
override fun prepare(query: SqlQuery, returnGeneratedKeys: Boolean): PreparedStatement {
val stmt = if (returnGeneratedKeys) {
// if (connection.driverName == "oracle.jdbc.driver.OracleDriver") {
// connection.underlying.prepareStatement(query.cleanStatement, autoGeneratedKeys.toTypedArray())
// } else {
// connection.underlying.prepareStatement(query.cleanStatement, Statement.RETURN_GENERATED_KEYS)
// }
connection.underlying.prepareStatement(query.cleanStatement, Statement.RETURN_GENERATED_KEYS)
} else {
connection.underlying.prepareStatement(query.cleanStatement)
}
query.populateParams(stmt)
return stmt
}
override fun prepare(query: SqlQueryBase<*>): PreparedStatement {
val stmt = connection.underlying.prepareStatement(query.cleanStatement)
query.populateParams(stmt)
return stmt
}
override fun prepare(query: SqlCall): CallableStatement {
val stmt = connection.underlying.prepareCall(query.cleanStatement)
query.populateParams(stmt)
return stmt
}
override fun query(query: SqlQueryBase<*>, consumer: (ResultSet) -> A): A {
return using(prepare(query)) { stmt ->
using(stmt.executeQuery()) { rs ->
consumer.invoke(rs)
}
}
}
override fun executeWithKeys(query: SqlQuery, consumer: (PreparedStatement) -> A): A? {
return using(prepare(query, true)) { stmt ->
if (stmt.execute()) {
if (connection.driverName == "oracle.jdbc.driver.OracleDriver") {
connection.underlying.prepareStatement(query.cleanStatement, autoGeneratedKeys.toTypedArray())
} else {
connection.underlying.prepareStatement(query.cleanStatement, Statement.RETURN_GENERATED_KEYS)
}
consumer.invoke(stmt)
} else {
null
}
}
}
override fun execute(query: SqlQueryBase<*>, consumer: (PreparedStatement) -> A): A? {
return using(prepare(query)) { stmt ->
if (stmt.execute()) {
consumer.invoke(stmt)
} else {
null
}
}
}
override fun execute(query: SqlCall, consumer: (CallableStatement) -> A): A? {
return using(prepare(query)) { stmt ->
if (stmt.execute()) {
consumer.invoke(stmt)
} else {
null
}
}
}
override fun updateWithKeys(query: SqlQuery, consumer: (PreparedStatement) -> A): A? {
return using(prepare(query, true)) { stmt ->
if (stmt.executeUpdate() > 0) {
consumer.invoke(stmt)
} else {
null
}
}
}
override fun update(query: SqlQueryBase<*>, consumer: (PreparedStatement) -> A): A? {
return using(prepare(query)) { stmt ->
if (stmt.executeUpdate() > 0) {
consumer.invoke(stmt)
} else {
null
}
}
}
override fun list(query: SqlQueryBase<*>, extractor: (Row) -> A): List {
return query(query) { rs ->
val rows = ArrayList()
Rows(rs).forEach {
rows.add(extractor.invoke(it))
}
rows
}
}
override fun jsonArray(query: SqlQueryBase<*>, extractor: (Row) -> JsonObject): JsonArray {
return query(query) { rs ->
val rows = MutableJsArray()
Rows(rs).forEach {
rows.add(extractor.invoke(it))
}
rows
}
}
override fun count(query: SqlQueryBase<*>): Int {
return query(query) { rs ->
Rows(rs).count()
}
}
override fun first(query: SqlQueryBase<*>, extractor: (Row) -> A): A? {
return query(query) { rs ->
if (rs.next()) {
extractor.invoke(Row(rs))
} else {
null
}
}
}
override fun hashMap(query: SqlQueryBase<*>, keyExtractor: (Row) -> K, extractor: (Row) -> A): Map {
return query(query) { rs ->
val rowMap = HashMap()
Rows(rs).forEach { row ->
rowMap[keyExtractor.invoke(row)] = extractor.invoke(row)
}
rowMap;
}
}
override fun jsonObject(query: SqlQueryBase<*>, keyExtractor: (Row) -> String, extractor: (Row) -> JsonObject): JsonObject {
return query(query) { rs ->
val rowMap = MutableJsObject()
Rows(rs).forEach { row ->
rowMap[keyExtractor.invoke(row)] = extractor.invoke(row)
}
rowMap;
}
}
override fun forEach(query: SqlQueryBase<*>, operator: (Row) -> Unit): Unit {
return query(query) { rs ->
Rows(rs).forEach { row ->
operator.invoke(row)
}
}
}
@Deprecated(message = "Use executeCall(query: SqlCall, stmtProc: (results: SqlCallResults) -> Unit) instead", replaceWith = ReplaceWith("executeCall"))
override fun forEach(query: SqlCall, stmtProc: (CallableStatement) -> Unit, operator: (rs: ResultSet, index: Int) -> Unit): Unit {
execute(query) { stmt: CallableStatement ->
var results = stmt.execute();
stmtProc.invoke(stmt as CallableStatement)
var rsIndex = 0
while (results) {
val rs = stmt.resultSet
operator.invoke(rs, rsIndex++)
results = stmt.moreResults
}
}
}
override fun executeCall(query: SqlCall, stmtProc: (results: SqlCallResults) -> Unit) {
execute(query) { stmt: CallableStatement ->
query.handleResults(stmt, stmtProc)
}
}
override fun execute(query: SqlQueryBase<*>): Boolean {
return using(prepare(query)) { stmt ->
stmt.execute()
}
}
override fun update(query: SqlQueryBase<*>): Int {
return using(prepare(query)) { stmt ->
stmt.executeUpdate()
}
}
override fun updateGetLongId(query: SqlQuery): Long? {
return updateWithKeys(query) { stmt ->
val rs = stmt.generatedKeys
if (rs.next()) rs.getLong(1)
else null
}
}
override fun updateGetId(query: SqlQuery): Int? {
return updateWithKeys(query) { stmt ->
val rs = stmt.generatedKeys
if (rs.next()) rs.getInt(1)
else null
}
}
override fun updateGetKey(query: SqlQuery, extractor: (Row) -> A): A? {
return updateWithKeys(query) { stmt ->
val rs = stmt.generatedKeys
if (rs.next()) extractor.invoke(Row(rs))
else null
}
}
override fun updateGetLongIds(query: SqlQuery): List? {
return updateWithKeys(query) { stmt ->
val keys = ArrayList()
val rs = stmt.generatedKeys
while (rs.next()) {
val id = rs.getLong(1)
if (!rs.wasNull()) keys.add(id)
}
keys
}
}
override fun updateGetIds(query: SqlQuery): List? {
return updateWithKeys(query) { stmt ->
val keys = ArrayList()
val rs = stmt.generatedKeys
while (rs.next()) {
val id = rs.getInt(1)
if (!rs.wasNull()) keys.add(id)
}
keys
}
}
override fun updateGetKeys(query: SqlQuery, extractor: (Row) -> A): List? {
return updateWithKeys(query) { stmt ->
val keys = ArrayList()
val rows = Rows(stmt.generatedKeys)
rows.forEach { row ->
val value = extractor.invoke(row)
keys.add(value)
}
keys
}
}
override fun transaction(operation: (Transaction) -> A): A {
try {
connection.begin()
val tx = TransactionImpl(connection, autoGeneratedKeys)
val result: A = operation.invoke(tx)
if (!connection.autoCommit) {
connection.commit()
}
return result
} catch (e: Exception) {
if (!connection.autoCommit) {
connection.rollback()
}
throw e
} finally {
if (!connection.autoCommit) {
connection.commit()
}
}
}
}