Skip to content

Commit

Permalink
fix!: EXPOSED-458 Stop sending default and null values in insert stat…
Browse files Browse the repository at this point in the history
…ements
  • Loading branch information
obabichevjb committed Sep 20, 2024
1 parent d3c60f2 commit ceb0c7b
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 120 deletions.
7 changes: 3 additions & 4 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -3063,7 +3063,6 @@ public abstract class org/jetbrains/exposed/sql/statements/BaseBatchInsertStatem
public fun prepared (Lorg/jetbrains/exposed/sql/Transaction;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;
public fun set (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Object;)V
public fun setArguments (Ljava/util/List;)V
protected fun valuesAndDefaults (Ljava/util/Map;)Ljava/util/Map;
}

public final class org/jetbrains/exposed/sql/statements/BatchDataInconsistentException : java/lang/Exception {
Expand Down Expand Up @@ -3106,7 +3105,6 @@ public class org/jetbrains/exposed/sql/statements/BatchUpsertStatement : org/jet
public final fun getOnUpdateExclude ()Ljava/util/List;
public final fun getWhere ()Lorg/jetbrains/exposed/sql/Op;
public fun insertValue (Lorg/jetbrains/exposed/sql/Column;)Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;
protected fun isColumnValuePreferredFromResultSet (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Object;)Z
public fun prepareSQL (Lorg/jetbrains/exposed/sql/Transaction;Z)Ljava/lang/String;
public fun prepared (Lorg/jetbrains/exposed/sql/Transaction;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;
public fun storeUpdateValues (Lkotlin/jvm/functions/Function2;)V
Expand Down Expand Up @@ -3169,6 +3167,7 @@ public class org/jetbrains/exposed/sql/statements/InsertStatement : org/jetbrain
public synthetic fun <init> (Lorg/jetbrains/exposed/sql/Table;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun arguments ()Ljava/lang/Iterable;
public fun arguments ()Ljava/util/List;
protected final fun clientDefaultColumns ()Ljava/util/List;
protected fun execInsertFunction (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;)Lkotlin/Pair;
public fun executeInternal (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/Integer;
public synthetic fun executeInternal (Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/Object;
Expand All @@ -3180,14 +3179,15 @@ public class org/jetbrains/exposed/sql/statements/InsertStatement : org/jetbrain
public final fun getOrNull (Lorg/jetbrains/exposed/sql/Column;)Ljava/lang/Object;
public final fun getResultedValues ()Ljava/util/List;
public final fun getTable ()Lorg/jetbrains/exposed/sql/Table;
protected fun isColumnValuePreferredFromResultSet (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Object;)Z
protected final fun isEntityIdClientSideGeneratedUUID (Lorg/jetbrains/exposed/sql/Column;)Z
public final fun isIgnore ()Z
public fun prepareSQL (Lorg/jetbrains/exposed/sql/Transaction;Z)Ljava/lang/String;
public fun prepared (Lorg/jetbrains/exposed/sql/Transaction;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;
public fun setArguments (Ljava/util/List;)V
public final fun setInsertedCount (I)V
protected final fun toSqlString (Ljava/util/List;Z)Ljava/lang/String;
protected fun valuesAndClientDefaults (Ljava/util/Map;)Ljava/util/Map;
public static synthetic fun valuesAndClientDefaults$default (Lorg/jetbrains/exposed/sql/statements/InsertStatement;Ljava/util/Map;ILjava/lang/Object;)Ljava/util/Map;
protected fun valuesAndDefaults (Ljava/util/Map;)Ljava/util/Map;
public static synthetic fun valuesAndDefaults$default (Lorg/jetbrains/exposed/sql/statements/InsertStatement;Ljava/util/Map;ILjava/lang/Object;)Ljava/util/Map;
}
Expand Down Expand Up @@ -3454,7 +3454,6 @@ public class org/jetbrains/exposed/sql/statements/UpsertStatement : org/jetbrain
public final fun getOnUpdateExclude ()Ljava/util/List;
public final fun getWhere ()Lorg/jetbrains/exposed/sql/Op;
public fun insertValue (Lorg/jetbrains/exposed/sql/Column;)Lorg/jetbrains/exposed/sql/ExpressionWithColumnType;
protected fun isColumnValuePreferredFromResultSet (Lorg/jetbrains/exposed/sql/Column;Ljava/lang/Object;)Z
public fun prepareSQL (Lorg/jetbrains/exposed/sql/Transaction;Z)Ljava/lang/String;
public fun prepared (Lorg/jetbrains/exposed/sql/Transaction;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/statements/api/PreparedStatementApi;
public fun storeUpdateValues (Lkotlin/jvm/functions/Function2;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ class Column<T>(
val expressionSQL = currentDialect.dataTypeProvider.processForDefaultValue(defaultValue)
if (!currentDialect.isAllowedAsColumnDefault(defaultValue)) {
val clientDefault = when {
defaultValueFun != null -> " Expression will be evaluated on the client."
// Check for client default value
defaultValueFun != null && dbDefaultValue == null -> " Expression will be evaluated on the client."
!columnType.nullable -> " Column will be created with NULL marker."
else -> ""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,11 @@ class BlobColumnType(
else -> error("Unexpected value of type Blob: $value of ${value::class.qualifiedName}")
}

override fun nonNullValueToString(value: ExposedBlob): String = currentDialect.dataTypeProvider.hexToDb(value.hexString())
override fun nonNullValueToString(value: ExposedBlob): String {
// For H2 Blobs the original dataTypeProvider must be taken (even if H2 in other DB mode)
return ((currentDialect as? H2Dialect)?.originalDataTypeProvider ?: currentDialect.dataTypeProvider)
.hexToDb(value.hexString())
}

override fun readObject(rs: ResultSet, index: Int) = when {
currentDialect is SQLServerDialect -> rs.getBytes(index)?.let(::ExposedBlob)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package org.jetbrains.exposed.sql.statements

import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.EntityIDColumnType
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.Transaction
import org.jetbrains.exposed.sql.isAutoInc
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
import org.jetbrains.exposed.sql.transactions.TransactionManager

Expand Down Expand Up @@ -88,18 +83,26 @@ abstract class BaseBatchInsertStatement(

override var arguments: List<List<Pair<Column<*>, Any?>>>? = null
get() = field ?: run {
val nullableColumns by lazy {
allColumnsInDataSet().filter { it.columnType.nullable && !it.isDatabaseGenerated }
}
data.map { single ->
val valuesAndDefaults = super.valuesAndDefaults(single) as MutableMap
val nullableMap = (nullableColumns - valuesAndDefaults.keys).associateWith { null }
valuesAndDefaults.putAll(nullableMap)
valuesAndDefaults.toList().sortedBy { it.first }
}.apply { field = this }
}
val columnsToInsert = (allColumnsInDataSet() + clientDefaultColumns()).toSet()

override fun valuesAndDefaults(values: Map<Column<*>, Any?>) = arguments!!.first().toMap()
data
.map { valuesAndClientDefaults(it) as MutableMap }
.map { values ->
columnsToInsert.map { column ->
column to when {
values.contains(column) -> values[column]
column.dbDefaultValue != null || column.isDatabaseGenerated -> DefaultValueMarker
else -> {
require(column.columnType.nullable) {
"The value for the column ${column.name} was not provided. " +
"The value for non-nullable column without defaults must be specified."
}
null
}
}
}
}.apply { field = this }
}

override fun prepared(transaction: Transaction, sql: String): PreparedStatementApi {
return if (!shouldReturnGeneratedValues) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,4 @@ open class BatchUpsertStatement(

return super.prepared(transaction, sql)
}

override fun isColumnValuePreferredFromResultSet(column: Column<*>, value: Any?): Boolean {
return isEntityIdClientSideGeneratedUUID(column) ||
super.isColumnValuePreferredFromResultSet(column, value)
}
}
Loading

0 comments on commit ceb0c7b

Please sign in to comment.