question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

optReference column should allow update { it[column] = nullableValue }

See original GitHub issue

See Users#cityId

object Cities : Table() {
    val id = integer("id").autoIncrement() // Column<Int>
    val name = varchar("name", 50) // Column<String>

    override val primaryKey = PrimaryKey(id, name = "PK_Cities_ID")
}

object Users : Table() {
    val id = varchar("id", 10) // Column<String>
    val name = varchar("name", length = 50) // Column<String>
    val cityId = optReference("city_id", Cities.id) // Column<Int?>

    override val primaryKey = PrimaryKey(id, name = "PK_User_ID") // name is optional here
}

Expected:

Users.insert {
    it[cityId] = null // should work, but it does not
    it[cityId] = 42 // should work, but it does not
}

Actual: code does not compile.

I suspect the issue is with UpdateBuilder#setWithEntityIdValue:

https://github.com/JetBrains/Exposed/blob/d59247283dc8c1af019e3e2a8c75c7519d1fdb6d/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/UpdateBuilder.kt#L33-L38

The type of optReference(...) is Column<EntityID<...>?> which is not compatible with ID : EntityID<E>.

It looks like the workaround is to permit Column<ID?>. For instance,

operator fun <S : Comparable<S>, ID : EntityID<S>?, E : S?> set(column: Column<ID>, value: E)

Unfortunately, that still allows users to store null to non-nullable columns (however, even the current code allows them to do so).

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:9

github_iconTop GitHub Comments

3reactions
vlsicommented, Jan 4, 2022

@Tapac , I’m inclined the issue should be reopened as Exposed still does not allow it[column] = nullableValue syntax.

0reactions
vlsicommented, Jul 27, 2022

My previous WA included a bug: it allowed to assign nullable value to a non-nullable column.

The better WA is as follows:

@Suppress("UNCHECKED_CAST")
operator fun <T, S : Comparable<S>, ID : EntityID<S>> UpdateBuilder<T>.set(column: Column<ID?>, value: S?) =
    // see https://github.com/JetBrains/Exposed/issues/1275
    set(column as Column<S?>, value)

The same pattern works for “custom casts”.

For instance, my database uses numeric(20) keys, however, it is convenient to use Longs in tests (since most of the time, the keys fit in Long).

So I created the following:

@JvmName("setEntityIdLong")
operator fun <T, ID: EntityID<BigDecimal>> UpdateBuilder<T>.set(column: Column<ID>, value: Long) =
    set(column, BigDecimal(value))

@Suppress("UNCHECKED_CAST")
@JvmName("setEntityIdLongNullable")
operator fun <T, ID: EntityID<BigDecimal>> UpdateBuilder<T>.set(column: Column<ID?>, value: Long?) =
    // see https://github.com/JetBrains/Exposed/issues/1275
    set(column as Column<BigDecimal?>, value?.let { BigDecimal(it) })

It enables “automatic” cast to BigDecimal in expressions like

Objects.merge {
    it[id] = 9164178420001991212 // id is decimal(...) column (which maps to BigDecimal)
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Change a Column to Allow NULL in SQL Server
If you have a column in a SQL Server table that does not allow NULL values and you need to change it to...
Read more >
Handling Null Values - ADO.NET - Microsoft Learn
Allowing null values in column definitions introduces three-valued logic into your application. A comparison can evaluate to one of three ...
Read more >
Altering a Column from Null to Not Null in SQL Server - Chartio
Alter a column from NULL to not NULL in SQL Server by updating existing column data and altering the column data structure to...
Read more >
Join SQL Server tables where columns include NULL values
By default SQL Server sets the column value to allow NULL values when creating new tables, unless other options are set. This is...
Read more >
Nullable reference types and nullability in EF Core
Let us look at what happens to a simple entity with some optional ... To make a column non-nullable, you must annotate its...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found