-
Notifications
You must be signed in to change notification settings - Fork 697
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-415 SchemaUtils incorrectly generates ALTER statements f… #2136
fix: EXPOSED-415 SchemaUtils incorrectly generates ALTER statements f… #2136
Conversation
…or existing nullable columns [MariaDB]
40c4c8e
to
ecc8a94
Compare
Probably, we could apply such a logic to MariaDB only, and still generate DDL with updating nullable columns for other DBs. But in this case I'd say the method It's definitely possible but would require to introduce at least one more constant (enum/object/..) like |
exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt
Outdated
Show resolved
Hide resolved
...d-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There may be a potential issue with the new MariaDB logic and b'
defaults. Please see the comments.
...ed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/ColumnDefinitionTests.kt
Outdated
Show resolved
Hide resolved
dialect is MysqlDialect || h2Mode == H2CompatibilityMode.MySQL || h2Mode == H2CompatibilityMode.MariaDB -> defaultValue.substringAfter( | ||
"b'" | ||
).trim('\'') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we have good enough test coverage to ok removing some of these branches. The h2Modes are probably not going to be an issue, but removing MariaDB from this substring check may cause problems in a few users.
One example I can think of:
In both MySQL and MariaDB, Exposed takes the opinion to store boolean values in BOOLEAN
column type instead of BIT
. But let's say a user has an existing table already in the DB that uses BIT
(or chooses to create one themselves), and they are using their own custom bool()
to register and work with this BIT
column using Kotlin booleans.
Attempting something like the following would no longer show the same behavior in both DB:
// represents the existing table in db
exec("CREATE TABLE IF NOT EXISTS tester (bool BIT DEFAULT b'0' NOT NULL)")
// represents the identical Exposed definition
object TestTable : Table("tester") {
val bool = bool("bool").default(false)
}
// when calling SchemaUtils.createMissingTables....
// MySQL - correctly does not generate ALTER statement
// MariaDB - incorrectly does generate ALTER statement
I'd suggest a third branch (if value starts with b'
or something) in the new MariaDB logic that does what the original logic did (i.e. what the new MySQL branch does now). Not sure if the mysql H2 modes would also be affected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added check of 'b
for MariaDB also, but without proper test actually.
But what I've found during testing of this is that binary
column is almost untested and quite broken.
I added test to check binary column ddl generation, and insert/reading values (with binary literal also, and the binary literal actually). So now it looks better, but PR become a bit bigger..
519f098
to
a363d9f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. I would still recommend moving the introduction of byteLiteral()
and the column changes to its own separate PR (why no byteParam()
btw?). It would be easier to look back on in case of anything and it could be merged first if the MariaDB tests depend on it.
|
||
@Suppress("MagicNumber") | ||
private fun ByteArray.toHexString(): String = joinToString("") { it.toString(16).uppercase().padStart(2, '0') } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this and above functionality already exists within the blob (binary) column type. For example, ExposedBlob
has the same function toHexString()
that can be extracted and reused.
But if you don't mind the duplicate here, at least nonNullValueToString()
should use currentDialect.dataTypeProvider.hexToDb(value.hexString())
. From what I'm seeing, existing hexToDb()
matches your branches above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO fix with EXPOSED-433 Check all the literals for default/insert/read operations
@Test | ||
fun testBinaryColumn() { | ||
val defaultValue = "default-value".toByteArray() | ||
val tester = object : IntIdTable("testBinaryColumn") { | ||
val bin = binary("bin", 256).default(defaultValue) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also move over existing tests from DDLTests.kt
: testBinaryWithoutLength()
and testBinary()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO fix with EXPOSED-433 Check all the literals for default/insert/read operations
val literalValue = "literal-value".toByteArray() | ||
val id2 = tester.insertAndGetId { it[tester.bin] = binaryLiteral(literalValue) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Literals are more meant to be used in query building, in WHERE clauses for example, or as column defaults, or where expressions are needed in functions. It might be good to at least test it it 1 of those actual use cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO fix with EXPOSED-433 Check all the literals for default/insert/read operations
057aa92
to
dba3d98
Compare
[![Mend Renovate](https://app.renovatebot.com/images/banner.svg)](https://renovatebot.com) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [org.jetbrains.exposed:exposed-jdbc](https://togithub.com/JetBrains/Exposed) | `0.52.0` -> `0.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.jetbrains.exposed:exposed-jdbc/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.jetbrains.exposed:exposed-jdbc/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.jetbrains.exposed:exposed-jdbc/0.52.0/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.jetbrains.exposed:exposed-jdbc/0.52.0/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | | [org.jetbrains.exposed:exposed-core](https://togithub.com/JetBrains/Exposed) | `0.52.0` -> `0.53.0` | [![age](https://developer.mend.io/api/mc/badges/age/maven/org.jetbrains.exposed:exposed-core/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/maven/org.jetbrains.exposed:exposed-core/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/maven/org.jetbrains.exposed:exposed-core/0.52.0/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/org.jetbrains.exposed:exposed-core/0.52.0/0.53.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- > [!WARNING] > Some dependencies could not be looked up. Check the Dependency Dashboard for more information. --- ### Release Notes <details> <summary>JetBrains/Exposed (org.jetbrains.exposed:exposed-jdbc)</summary> ### [`v0.53.0`](https://togithub.com/JetBrains/Exposed/blob/HEAD/CHANGELOG.md#0530) [Compare Source](https://togithub.com/JetBrains/Exposed/compare/0.52.0...0.53.0) Infrastructure: - SQLite driver 3.46.0.1 - Spring Framework 6.1.11 - Spring Boot 3.3.2 - junit-bom 5.10.3 Features: - feat: Add time extension function for temporal expressions in Kotlin and Java by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2121](https://togithub.com/JetBrains/Exposed/pull/2121) - feat: EXPOSED-435 Allow insertReturning() to set isIgnore = true by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2148](https://togithub.com/JetBrains/Exposed/pull/2148) - feat: EXPOSED-77 Support entity class for table with composite primary key by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/1987](https://togithub.com/JetBrains/Exposed/pull/1987) - feat: EXPOSED-446 Support N-column inList equality comparisons by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2157](https://togithub.com/JetBrains/Exposed/pull/2157) - feat: EXPOSED-450 Merge command: PostgreSQL improvements by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2161](https://togithub.com/JetBrains/Exposed/pull/2161) - feat: EXPOSED-388 Support for column type converters by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2143](https://togithub.com/JetBrains/Exposed/pull/2143) - Adding comment text for a query SQL by [@​xJoeWoo](https://togithub.com/xJoeWoo) in [https://github.com/JetBrains/Exposed/pull/2088](https://togithub.com/JetBrains/Exposed/pull/2088) - feat: EXPOSED-459 Open AbstractQuery.copyTo() to allow custom Query class extension by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2173](https://togithub.com/JetBrains/Exposed/pull/2173) - feat: EXPOSED-461 Add time column in Joda-Time module by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2175](https://togithub.com/JetBrains/Exposed/pull/2175) Bug fixes: - fix: EXPOSED-424 ClassCastException exception when using `fetchBatchedResults` with `alias` by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2140](https://togithub.com/JetBrains/Exposed/pull/2140) - fix: EXPOSED-407 compositeMoney() nullability definition issues by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2137](https://togithub.com/JetBrains/Exposed/pull/2137) - fix: EXPOSED-415 SchemaUtils incorrectly generates ALTER statements for existing nullable columns by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2136](https://togithub.com/JetBrains/Exposed/pull/2136) - fix: EXPOSED-363 LocalTime and literal(LocalTime) are not the same by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2152](https://togithub.com/JetBrains/Exposed/pull/2152) - fix: EXPOSED-432 CurrentDate default is generated as null in MariaDB by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2149](https://togithub.com/JetBrains/Exposed/pull/2149) - fix: Allow column reference in default expressions for MySQL and MariaDB by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2159](https://togithub.com/JetBrains/Exposed/pull/2159) - fix: EXPOSED-430 Insert and BatchInsert do not return default values by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2158](https://togithub.com/JetBrains/Exposed/pull/2158) - fix: EXPOSED-452 Flaky H2\_Oracle test `testTimestampWithTimeZoneDefaults` by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2169](https://togithub.com/JetBrains/Exposed/pull/2169) - EXPOSED-457 The column default value always compares unequal by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2170](https://togithub.com/JetBrains/Exposed/pull/2170) - EXPOSED-409 Custom primary key. Access to the primary key fails with ClassCastException by [@​obabichevjb](https://togithub.com/obabichevjb) in [https://github.com/JetBrains/Exposed/pull/2151](https://togithub.com/JetBrains/Exposed/pull/2151) - fix: EXPOSED-447 Eager loading does not work with composite PK entity by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2177](https://togithub.com/JetBrains/Exposed/pull/2177) Docs: - chore: Add migration sample by [@​joc-a](https://togithub.com/joc-a) in [https://github.com/JetBrains/Exposed/pull/2144](https://togithub.com/JetBrains/Exposed/pull/2144) - docs: Change repetitionAttempts to maxAttempts in website docs by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2164](https://togithub.com/JetBrains/Exposed/pull/2164) - docs: EXPOSED-445 Add documentation for DSL & DAO composite primary keys by [@​bog-walk](https://togithub.com/bog-walk) in [https://github.com/JetBrains/Exposed/pull/2165](https://togithub.com/JetBrains/Exposed/pull/2165) - docs: EXPOSED-419 Rework the getting started tutorial by [@​vnikolova](https://togithub.com/vnikolova) in [https://github.com/JetBrains/Exposed/pull/2160](https://togithub.com/JetBrains/Exposed/pull/2160) - Configure API documentation for Exposed by [@​e5l](https://togithub.com/e5l) in [https://github.com/JetBrains/Exposed/pull/2171](https://togithub.com/JetBrains/Exposed/pull/2171) </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://www.mend.io/free-developer-tools/renovate/). View the [repository job log](https://developer.mend.io/github/DonRobo/home-former). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy40NDAuNyIsInVwZGF0ZWRJblZlciI6IjM3LjQ0MC43IiwidGFyZ2V0QnJhbmNoIjoiZGV2ZWxvcCIsImxhYmVscyI6W119--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Here is the fix of generation update with
SchemaUtils.statementsRequiredToActualizeScheme()
for nullable columns.The problem is that for MariaDB and MySql it's not possible to determine whether the default value of a nullable column was not defined or it was explicitly set to
null
. Also an issue that (if I'm right for MySql only) for some cases string default value"NULL"
was recognized as null.The main change that I made with this PR is treating any null-like value (non set
null
, or explicitly setnull
) as the same for DDL generation purposes. It means that if a user created a table with a nullable column and without a default value and then added explicit.default(null)
Exposed will not offer to alter that column. Such a variant is not 100% accurate in terms of synchronization between actual DB and Exposed definitions but looks like follows to the same result.It was suggested to check if we can take the information about the default values directly from DB (instead of JDBC), but looks like it's the same for MariaDB anyway.