Skip to content

Commit

Permalink
fix!: EXPOSED-285 Time default falsely triggers ALTER statement
Browse files Browse the repository at this point in the history
-`KotlinLocalTimeColumnType` now overrides `nonNullValueAsDefaultString` to match the default value obtained from the metadata for PostgreSQL.
-In `nonNullValueToString` for `KotlinLocalTimeColumnType`, the formatted String for MySQL did not match the format received from the metadata, so a new formatter specific to MySQL is now used.
  • Loading branch information
joc-a committed Feb 5, 2024
1 parent e1c6868 commit 35b054b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
1 change: 1 addition & 0 deletions exposed-kotlin-datetime/api/exposed-kotlin-datetime.api
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ public final class org/jetbrains/exposed/sql/kotlin/datetime/KotlinLocalTimeColu
public static final field Companion Lorg/jetbrains/exposed/sql/kotlin/datetime/KotlinLocalTimeColumnType$Companion;
public fun <init> ()V
public fun getHasTimePart ()Z
public fun nonNullValueAsDefaultString (Ljava/lang/Object;)Ljava/lang/String;
public fun nonNullValueToString (Ljava/lang/Object;)Ljava/lang/String;
public fun notNullValueToDB (Ljava/lang/Object;)Ljava/lang/Object;
public fun sqlType ()Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ private val ORACLE_TIME_STRING_FORMATTER by lazy {
).withZone(ZoneId.of("UTC"))
}

private val MYSQL_TIME_STRING_FORMATTER by lazy {
DateTimeFormatter.ofPattern(
"HH:mm:ss",
Locale.ROOT
).withZone(ZoneId.systemDefault())
}

private val DEFAULT_TIME_STRING_FORMATTER by lazy {
DateTimeFormatter.ISO_LOCAL_TIME.withLocale(Locale.ROOT).withZone(ZoneId.systemDefault())
}
Expand Down Expand Up @@ -237,10 +244,10 @@ class KotlinLocalTimeColumnType : ColumnType(), IDateColumnType {
override fun sqlType(): String = currentDialect.dataTypeProvider.timeType()

override fun nonNullValueToString(value: Any): String {
val formatter = if (currentDialect is OracleDialect || currentDialect.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) {
ORACLE_TIME_STRING_FORMATTER
} else {
DEFAULT_TIME_STRING_FORMATTER
val formatter = when {
currentDialect is OracleDialect || currentDialect.h2Mode == H2Dialect.H2CompatibilityMode.Oracle -> ORACLE_TIME_STRING_FORMATTER
currentDialect is MysqlDialect -> MYSQL_TIME_STRING_FORMATTER
else -> DEFAULT_TIME_STRING_FORMATTER
}

val instant = when (value) {
Expand Down Expand Up @@ -275,6 +282,11 @@ class KotlinLocalTimeColumnType : ColumnType(), IDateColumnType {
else -> value
}

override fun nonNullValueAsDefaultString(value: Any): String = when (currentDialect) {
is PostgreSQLDialect -> "${nonNullValueToString(value)}::time without time zone"
else -> super.nonNullValueAsDefaultString(value)
}

private fun longToLocalTime(millis: Long) = Instant.fromEpochMilliseconds(millis).toLocalDateTime(DEFAULT_TIME_ZONE).time

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,20 @@ class DefaultsTest : DatabaseTestsBase() {
}
}

@Test
fun testTimeDefaultDoesNotTriggerAlterStatement() {
val time = Clock.System.now().toLocalDateTime(TimeZone.of("Japan")).time

val tester = object : Table("tester") {
val timeWithDefault = time("timeWithDefault").default(time)
}

withTables(tester) {
val statements = SchemaUtils.addMissingColumnsStatements(tester)
assertEquals(0, statements.size)
}
}

@Test
fun testTimestampDefaultDoesNotTriggerAlterStatement() {
val instant = Clock.System.now() // In UTC
Expand Down

0 comments on commit 35b054b

Please sign in to comment.