Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix! EXPOSED-458 Stop sending default and null values in insert state… #2295

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -3091,7 +3091,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 @@ -3134,7 +3133,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 @@ -3197,6 +3195,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 @@ -3208,14 +3207,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 final 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 @@ -3482,7 +3482,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 @@ -126,7 +126,7 @@ 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."
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 @@ -374,6 +374,10 @@ open class ColumnWithTransform<Unwrapped, Wrapped>(
}
}

internal fun unwrapColumnValues(values: Map<Column<*>, Any?>): Map<Column<*>, Any?> = values.mapValues { (col, value) ->
value?.let { (col.columnType as? ColumnWithTransform<Any, Any>)?.unwrapRecursive(it) } ?: value
}

/**
* A class that handles the transformation between a source column type and a target type,
* but also supports transformations involving `null` values.
Expand Down Expand Up @@ -1014,7 +1018,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 @@ -3,6 +3,7 @@ package org.jetbrains.exposed.sql.statements
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.statements.api.PreparedStatementApi
import org.jetbrains.exposed.sql.vendors.MysqlFunctionProvider
import org.jetbrains.exposed.sql.vendors.OracleDialect
import org.jetbrains.exposed.sql.vendors.currentDialect

/**
Expand Down Expand Up @@ -54,8 +55,9 @@ open class BatchUpsertStatement(
val keyColumns = if (functionProvider is MysqlFunctionProvider) keys.toList() else getKeyColumns(keys = keys)
val insertValues = arguments!!.first()
val insertValuesSql = insertValues.toSqlString(prepared)
val updateExcludeColumns = (onUpdateExclude ?: emptyList()) + if (dialect is OracleDialect) keyColumns else emptyList()
val updateExpressions = updateValues.takeIf { it.isNotEmpty() }?.toList()
?: getUpdateExpressions(insertValues.unzip().first, onUpdateExclude, keyColumns)
?: getUpdateExpressions(insertValues.unzip().first, updateExcludeColumns, keyColumns)
return functionProvider.upsert(table, insertValues, insertValuesSql, updateExpressions, keyColumns, where, transaction)
}

Expand All @@ -74,9 +76,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
Loading