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

com.sxtanna.db.Kuery.kt Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
package com.sxtanna.db

import com.sxtanna.db.config.KueryConfig
import com.sxtanna.db.struct.Table
import com.sxtanna.db.struct.statement.Select1
import com.sxtanna.db.type.Executed
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import org.intellij.lang.annotations.Language
import org.slf4j.Logger
import org.slf4j.LoggerFactory.getLogger
import java.sql.Connection
import java.sql.PreparedStatement
import java.sql.ResultSet

/**
 * SQL Pool wrapper
 */
class Kuery(private val config : KueryConfig, internal val logger : Logger = getLogger("Kuery-${config.pool.name}")) {

    private lateinit var pool : HikariDataSource

    /**
     * Create the pool from the given config
     */
    fun load() {
        logger.debug("Kuery is loading")
        check(::pool.isInitialized.not()) { "Kuery is already loaded" }

        val config = HikariConfig().apply {
            driverClassName = "org.mariadb.jdbc.Driver"

            jdbcUrl = "jdbc:mysql://${config.data.address}:${config.data.port}/${config.data.database}?useSSL=false"

            // oof
            config.pool.name.takeIf { it.isNotBlank() }?.let { poolName = it }

            maximumPoolSize = config.pool.size
            idleTimeout = config.pool.idleTimeout
            connectionTimeout = config.pool.connTimeout

            username = config.user.name
            password = config.user.auth

            addDataSourceProperty("cachePrepStmts", true)
            addDataSourceProperty("prepStmtCacheSize", 250)
            addDataSourceProperty("prepStmtCacheSqlLimit", 2048)
            addDataSourceProperty("useServerPrepStmts", true)
            addDataSourceProperty("cacheCallableStmts", true)
            addDataSourceProperty("elideSetAutoCommits", true)
            addDataSourceProperty("useLocalSessionState", true)
            addDataSourceProperty("alwaysSendSetIsolation", true)
            addDataSourceProperty("cacheResultSetMetadata", true)
            addDataSourceProperty("cacheServerConfiguration", true)
        }

        pool = HikariDataSource(config)
    }

    /**
     * Unload the pool after it's been loaded
     */
    fun unload() {
        logger.debug("Kuery is unloading")
        check(::pool.isInitialized) { "Kuery is not loaded" }

        pool.close()
    }


    /**
     * Pull a connection from the pool
     */
    private fun connect() : Connection = pool.connection

    /**
     * Use a connection from the pool
     *  * Closes automatically after code block
     */
    private fun  connect(block : (Connection) -> R) = connect().use(block)


    /**
     * Create a [KueryTask] from this [Kuery] instance
     *  * Connection does not close immediately
     */
    operator fun invoke() : KueryTask = KueryTask(this, connect())

    /**
     * Create a [KueryTaskTable] from this [Kuery] instance
     *  * Connection does not close immediately
     */
    operator fun  invoke(table : Table) = KueryTaskTable(table, invoke())


    /**
     * Execute database operations using [KueryTask]
     *  * Connection closes immediately after code block
     *
     *  @return Optional result of database operations
     */
    operator fun  invoke(block : KueryTask.() -> R) : R {
        return connect {
            val result = KueryTask(this, it).let(block)
            if (result is Executed) result.execute()
            if (result is Select1<*, *>) result.component1()

            result
        }
    }

    /**
     * Execute database operations using [KueryTaskTable]
     *  * Connection closes immediately after code block
     *
     *  @return Optional result of database operations
     */
    operator fun  invoke(table : Table, block : KueryTaskTable.() -> R) : R {
        return connect {
            val result = KueryTaskTable(table, KueryTask(this, it)).let(block)
            if (result is Executed) result.execute()
            if (result is Select1<*, *>) result.component1()

            result
        }
    }


    /**
     * Execute a statement
     */
    internal fun Connection.push(@Language("MySQL") statement : String, block : PreparedStatement.() -> Unit = {}) {
        prepareStatement(statement).apply(block).execute()
    }

    /**
     * Execute a query
     */
    internal fun Connection.pull(@Language("MySQL") statement : String, block : PreparedStatement.() -> Unit = {}) : ResultSet {
        return prepareStatement(statement).apply(block).executeQuery()
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy