com.dbobjekts.statement.insert.InsertStatementExecutor.kt Maven / Gradle / Ivy
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