From f1b88a7d207ca572d4f7cc61cae1c3b46671003d Mon Sep 17 00:00:00 2001 From: "Andrey.Tarashevskiy" Date: Mon, 19 Apr 2021 01:41:19 +0300 Subject: [PATCH] Fixes after merging LocalTime support PRs --- .../org/jetbrains/exposed/gradle/Versions.kt | 2 +- .../sql/java-time/JavaDateColumnType.kt | 77 ++++--------------- .../sql/java-time/JavaDateFunctions.kt | 5 +- .../org/jetbrains/exposed/JavaTimeTests.kt | 2 + .../org/jetbrains/exposed/MiscTableTest.kt | 31 ++++---- 5 files changed, 36 insertions(+), 81 deletions(-) diff --git a/buildSrc/src/main/kotlin/org/jetbrains/exposed/gradle/Versions.kt b/buildSrc/src/main/kotlin/org/jetbrains/exposed/gradle/Versions.kt index ed156e1c5f..9060cd053e 100644 --- a/buildSrc/src/main/kotlin/org/jetbrains/exposed/gradle/Versions.kt +++ b/buildSrc/src/main/kotlin/org/jetbrains/exposed/gradle/Versions.kt @@ -10,7 +10,7 @@ object Versions { const val mysql51 = "5.1.49" const val mysql80 = "8.0.23" const val oracle12 = "12.2.0.1" - const val postgre = "42.2.18.jre6" + const val postgre = "42.2.19" const val postgreNG = "0.8.6" const val sqlLite3 = "3.32.3.2" const val sqlserver = "8.4.1.jre8" diff --git a/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateColumnType.kt b/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateColumnType.kt index f218d179eb..01ee21f3f3 100644 --- a/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateColumnType.kt +++ b/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateColumnType.kt @@ -15,16 +15,13 @@ import java.util.* private val DEFAULT_DATE_STRING_FORMATTER by lazy { DateTimeFormatter.ISO_LOCAL_DATE.withLocale(Locale.ROOT).withZone(ZoneId.systemDefault()) } -private val DEFAULT_TIME_STRING_FORMATTER by lazy { - DateTimeFormatter.ISO_LOCAL_TIME.withLocale(Locale.ROOT).withZone(ZoneId.systemDefault()) -} private val DEFAULT_DATE_TIME_STRING_FORMATTER by lazy { DateTimeFormatter.ISO_LOCAL_DATE_TIME.withLocale(Locale.ROOT).withZone(ZoneId.systemDefault()) } private val SQLITE_AND_ORACLE_DATE_TIME_STRING_FORMATTER by lazy { DateTimeFormatter.ofPattern( - "yyyy-MM-dd HH:mm:ss.SSS", - Locale.ROOT + "yyyy-MM-dd HH:mm:ss.SSS", + Locale.ROOT ).withZone(ZoneId.systemDefault()) } private val DEFAULT_TIME_STRING_FORMATTER by lazy { @@ -86,49 +83,6 @@ class JavaLocalDateColumnType : ColumnType(), IDateColumnType { } } -class JavaLocalTimeColumnType : ColumnType(), IDateColumnType { - override val hasTimePart: Boolean = true - - override fun sqlType(): String = "TIME" - - override fun nonNullValueToString(value: Any): String { - val dummyDate: LocalDate = LocalDate.now() // Dummy date to build Instant - val instant = when (value) { - is String -> return value - is LocalTime -> Instant.from(LocalDateTime.of(dummyDate, value).atZone(ZoneId.systemDefault())) - is java.sql.Time -> Instant.from(LocalDateTime.of(dummyDate, value.toLocalTime()).atZone(ZoneId.systemDefault())) - is java.sql.Timestamp -> Instant.from(LocalDateTime.of(dummyDate, value.toLocalDateTime().atZone(ZoneId.systemDefault()).toLocalTime())) - else -> error("Unexpected value: $value of ${value::class.qualifiedName}") - } - - return "'${DEFAULT_TIME_STRING_FORMATTER.format(instant)}'" - } - - override fun valueFromDB(value: Any): Any = when (value) { - is LocalTime -> value - is java.sql.Time -> value.toLocalTime() - is java.sql.Timestamp -> value.toLocalDateTime().toLocalTime() - is Int -> longToLocalTime(value.toLong()) - is Long -> longToLocalTime(value) - is String -> when (currentDialect) { - is SQLiteDialect -> LocalTime.parse(value) - else -> value - } - else -> LocalTime.parse(value.toString()) - } - - override fun notNullValueToDB(value: Any): Any = when { - value is LocalTime -> java.sql.Time.valueOf(value) - else -> value - } - - private fun longToLocalTime(instant: Long) = Instant.ofEpochMilli(instant).atZone(ZoneId.systemDefault()).toLocalTime() - - companion object { - internal val INSTANCE = JavaLocalTimeColumnType() - } -} - class JavaLocalDateTimeColumnType : ColumnType(), IDateColumnType { override val hasTimePart: Boolean = true override fun sqlType(): String = currentDialect.dataTypeProvider.dateTimeType() @@ -174,37 +128,39 @@ class JavaLocalDateTimeColumnType : ColumnType(), IDateColumnType { } } -class JavaLocalTimeColumnType : ColumnType() { +class JavaLocalTimeColumnType : ColumnType(), IDateColumnType { + override val hasTimePart: Boolean = true + override fun sqlType(): String = currentDialect.dataTypeProvider.timeType() override fun nonNullValueToString(value: Any): String { val instant = when (value) { is String -> return value - is LocalTime -> return value.toString() - is java.sql.Time -> Instant.ofEpochMilli(value.time) + is LocalTime -> value + is java.sql.Time -> Instant.ofEpochMilli(value.time).atZone(ZoneId.systemDefault()) + is java.sql.Timestamp -> Instant.ofEpochMilli(value.time).atZone(ZoneId.systemDefault()) else -> error("Unexpected value: $value of ${value::class.qualifiedName}") } return "'${DEFAULT_TIME_STRING_FORMATTER.format(instant)}'" } - override fun valueFromDB(value: Any): LocalTime = (when (value) { + override fun valueFromDB(value: Any): LocalTime = when (value) { is LocalTime -> value - is java.sql.Time -> longToLocalTime(value.time) - is java.sql.Timestamp -> longToLocalTime(value.time / 1000, value.nanos.toLong()) + is java.sql.Time -> value.toLocalTime() + is java.sql.Timestamp -> value.toLocalDateTime().toLocalTime() is Int -> longToLocalTime(value.toLong()) is Long -> longToLocalTime(value) is String -> LocalTime.parse(value, formatterForTimeString(value)) else -> valueFromDB(value.toString()) - }.withNano(0)) + } override fun notNullValueToDB(value: Any): Any = when (value) { - is LocalDateTime -> DEFAULT_TIME_STRING_FORMATTER.format(value.atZone(ZoneId.systemDefault())) + is LocalTime -> java.sql.Time.valueOf(value) else -> value } private fun longToLocalTime(millis: Long) = Instant.ofEpochMilli(millis).atZone(ZoneId.systemDefault()).toLocalTime() - private fun longToLocalTime(seconds: Long, nanos: Long) = Instant.ofEpochSecond(seconds, nanos).atZone(ZoneId.systemDefault()).toLocalTime() companion object { internal val INSTANCE = JavaLocalTimeColumnType() @@ -298,13 +254,6 @@ class JavaDurationColumnType : ColumnType() { */ fun Table.date(name: String): Column = registerColumn(name, JavaLocalDateColumnType()) -/** - * A time column to store a time. - * - * @param name The column name - */ -fun Table.time(name: String): Column = registerColumn(name, JavaLocalTimeColumnType()) - /** * A datetime column to store both a date and a time. * diff --git a/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateFunctions.kt b/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateFunctions.kt index 5823a5c359..92d2592e56 100644 --- a/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateFunctions.kt +++ b/exposed-java-time/src/main/kotlin/org/jetbrains/exposed/sql/java-time/JavaDateFunctions.kt @@ -11,7 +11,7 @@ class Date(val expr: Expression) : Function(JavaLoc override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder { append("DATE(", expr, ")") } } -class Time(val expr: Expression) : Function(JavaLocalTimeColumnType.INSTANCE) { +class Time(val expr: Expression) : Function(JavaLocalTimeColumnType.INSTANCE) { override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder { append("Time(", expr, ")") } } @@ -88,8 +88,7 @@ fun durationParam(value: Duration): Expression = QueryParameter(value, fun dateLiteral(value: LocalDate): LiteralOp = LiteralOp(JavaLocalDateColumnType.INSTANCE, value) fun timeLiteral(value: LocalTime): LiteralOp = LiteralOp(JavaLocalTimeColumnType.INSTANCE, value) -fun dateTimeLiteral(value: LocalDateTime): LiteralOp = - LiteralOp(JavaLocalDateTimeColumnType.INSTANCE, value) +fun dateTimeLiteral(value: LocalDateTime): LiteralOp = LiteralOp(JavaLocalDateTimeColumnType.INSTANCE, value) fun timestampLiteral(value: Instant): LiteralOp = LiteralOp(JavaInstantColumnType.INSTANCE, value) fun durationLiteral(value: Duration): LiteralOp = LiteralOp(JavaDurationColumnType.INSTANCE, value) diff --git a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/JavaTimeTests.kt b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/JavaTimeTests.kt index 511e4c9458..54574ce7c8 100644 --- a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/JavaTimeTests.kt +++ b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/JavaTimeTests.kt @@ -84,6 +84,8 @@ fun assertEqualDateTime(d1: T?, d2: T?) { d1 is Instant && d2 is Instant && (currentDialectTest as? MysqlDialect)?.isFractionDateTimeSupported() == false -> assertEquals(d1.toEpochMilli() / 1000, d2.toEpochMilli() / 1000, "Failed on ${currentDialectTest.name}") d1 is Instant && d2 is Instant -> assertEquals(d1.toEpochMilli(), d2.toEpochMilli(), "Failed on ${currentDialectTest.name}") + d1 is LocalTime && d2 is LocalTime && d2.nano == 0 -> assertEquals(d1.withNano(0), d2, "Failed on ${currentDialectTest.name}") + d1 is LocalTime && d2 is LocalTime -> assertEquals(d1, d2, "Failed on ${currentDialectTest.name}") d1 is LocalDateTime && d2 is LocalDateTime -> { val d1Millis = Instant.from(d1.atZone(ZoneId.systemDefault())).toEpochMilli() val d2Millis = Instant.from(d2.atZone(ZoneId.systemDefault())).toEpochMilli() diff --git a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/MiscTableTest.kt b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/MiscTableTest.kt index 151135e7ed..f917439cc9 100644 --- a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/MiscTableTest.kt +++ b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/MiscTableTest.kt @@ -2,9 +2,9 @@ package org.jetbrains.exposed import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.`java-time`.date -import org.jetbrains.exposed.sql.`java-time`.time import org.jetbrains.exposed.sql.`java-time`.datetime import org.jetbrains.exposed.sql.`java-time`.duration +import org.jetbrains.exposed.sql.`java-time`.time import org.jetbrains.exposed.sql.`java-time`.timestamp import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.TestDB @@ -317,7 +317,8 @@ class MiscTableTest : DatabaseTestsBase() { d = date, dn = null, t = time, - tn = null,dt = dateTime, + tn = null, + dt = dateTime, dtn = null, ts = timestamp, tsn = null, @@ -1115,8 +1116,8 @@ class MiscTableTest : DatabaseTestsBase() { dn = null, t = time, tn = null, - d = dateTime, - dn = null, + dt = dateTime, + dtn = null, ts = timestamp, tsn = null, dr = duration, @@ -1147,7 +1148,7 @@ class MiscTableTest : DatabaseTestsBase() { val duration = Duration.ofMinutes(1) val eOne = MiscTable.E.ONE val dec = BigDecimal("239.42") - withTables(excludeSettings = listOf(TestDB.MYSQL, TestDB.MARIADB), tables = *arrayOf(tbl)) { + withTables(excludeSettings = listOf(TestDB.MYSQL, TestDB.MARIADB), tables = arrayOf(tbl)) { tbl.insert { it[by] = 13 it[sm] = -10 @@ -1185,8 +1186,8 @@ class MiscTableTest : DatabaseTestsBase() { dn = null, t = time, tn = null, - d = dateTime, - dn = null, + dt = dateTime, + dtn = null, ts = timestamp, tsn = null, dr = duration, @@ -1216,8 +1217,10 @@ fun Misc.checkRowFull( smn: Short?, n: Int, nn: Int?, - t: LocalDate, - tn: LocalDate?, + d: LocalDate, + dn: LocalDate?, + t: LocalTime, + tn: LocalTime?, dt: LocalDateTime, dtn: LocalDateTime?, ts: Instant, @@ -1245,8 +1248,10 @@ fun Misc.checkRowDates( row: ResultRow, d: LocalDate, dn: LocalDate?, - t: LocalDateTime, - tn: LocalDateTime?, + t: LocalTime, + tn: LocalTime?, + dt: LocalDateTime, + dtn: LocalDateTime?, ts: Instant, tsn: Instant? = null, dr: Duration, @@ -1254,8 +1259,8 @@ fun Misc.checkRowDates( ) { assertEqualDateTime(d, row[this.d]) assertEqualDateTime(dn, row[this.dn]) - assertEqualDateTime(t.withNano(0), row[this.t]) - assertEqualDateTime(tn?.withNano(0), row[this.tn]) + assertEqualDateTime(t, row[this.t]) + assertEqualDateTime(tn, row[this.tn]) assertEqualDateTime(dt, row[this.dt]) assertEqualDateTime(dtn, row[this.dtn]) assertEqualDateTime(ts, row[this.ts])