All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vladsch.kotlin.jdbc.SessionImpl.kt Maven / Gradle / Ivy

Go to download

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()
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy