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

com.dbobjekts.statement.insert.InsertStatementExecutor.kt Maven / Gradle / Ivy

There is a newer version: 0.6.0-RC2
Show newest version
package com.dbobjekts.statement.insert

import com.dbobjekts.api.AnyColumnAndValue
import com.dbobjekts.api.AnySqlParameter
import com.dbobjekts.statement.Semaphore
import com.dbobjekts.api.exception.StatementBuilderException
import com.dbobjekts.jdbc.ConnectionAdapter
import com.dbobjekts.metadata.Catalog
import com.dbobjekts.metadata.column.AutoKeyColumn
import com.dbobjekts.metadata.column.SequenceKeyColumn
import com.dbobjekts.statement.ColumnsForUpdate
import com.dbobjekts.statement.StatementBase
import com.dbobjekts.util.StringUtil
import com.dbobjekts.vendors.VendorSpecificProperties
import org.slf4j.LoggerFactory

class InsertStatementExecutor(
    semaphore: Semaphore,
    connection: ConnectionAdapter,
    val values: List,
    val vendorSpecificProperties: VendorSpecificProperties
) : StatementBase(semaphore, connection) {

    private val log = LoggerFactory.getLogger(InsertStatementExecutor::class.java)
    override val statementType = "insert"
    override val catalog: Catalog = connection.catalog()

    protected val columnsForUpdate = ColumnsForUpdate()

    init {
        registerTablesInColumn(values)
    }


    fun parameters(): List = columnsForUpdate.params.toList()

    /**
     * Executes the insert statement.
     * @param if the table uses an auto-generated numeric primary key, this value is returned. Otherwise, it returns the value returned by [java.sql.PreparedStatement.executeUpdate]
     */
    fun execute(): Long {
        val pk = getTable().primaryKey()
        try {
            return if (pk == null) {
                values.forEach { columnsForUpdate.addParam(it) }
                val sql = toSQL()
                val plh = parameters()
                connection.prepareAndExecuteUpdate(sql, plh)
            } else {
                when (pk) {
                    is SequenceKeyColumn<*> -> {
                        val sequenceSql =
                            generateSequencePattern() ?: throw StatementBuilderException("sequence pattern cannot be empty")
                        val newKeyValue: Long =
                            createKeyFromSequence(connection, String.format(sequenceSql, pk.qualifiedSequence()))
                        columnsForUpdate.addParam(pk.createValueForUpdate(newKeyValue))
                        values.forEach { columnsForUpdate.addParam(it) }
                        val sql = toSQL()
                        connection.prepareAndExecuteUpdate(sql, parameters())
                        newKeyValue
                    }

                    is AutoKeyColumn<*> -> {
                        values.forEach { columnsForUpdate.addParam(it) }
                        connection.executeInsertWithAutoGeneratedKey(toSQL(), parameters())
                    }

                    else -> throw StatementBuilderException("primary key must be SequenceKeyColumn or AutoKeyColumn")
                }
            }
        } finally {
          semaphore.clear()
        }
    }

    private fun createKeyFromSequence(
        connection: ConnectionAdapter,
        sql: String
    ): Long = connection.fetchKey(sql) ?: 0

    private fun toSQL(): String {
        val columns = columnsForUpdate.getCommaSeparatedColumnList()
        val values = columnsForUpdate.getCommaSeparatedQuestionMarks()
        return StringUtil.concat(
            listOf(
                "insert into",
                getTable().schemaAndName(),
                "($columns)",
                "values",
                "($values)"
            )
        )
    }

    fun generateSequencePattern(): String? = vendorSpecificProperties.sequencePattern()

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy