Skip to content

Commit

Permalink
test: Fix failing datetime comparison tests in Oracle (JetBrains#1813)
Browse files Browse the repository at this point in the history
* test: Fix failing datetime comparison tests in Oracle

In both exposed-java-time and exposed-kotlin-datetime modules:

MiscTableTest/testSelect01()
MiscTableTest/testSelect02()

Fails with an internal equality comparison issue due to precision.

The datetime() column maps to TIMESTAMP without specifying a precision, so each
DB defaults to a certain number of digits. This number is 6 in Oracle, and the
value is round up internally instead of being truncated.

Explicitly casting the datetime literal in the WHERE clause causes the appropriate
comparison to occur.

A new unit test specifically for this issue showed that the same issue was also
occurring in certain H2 modes, causing flaky local tests.
  • Loading branch information
bog-walk authored and saral committed Oct 3, 2023
1 parent b7e2c15 commit bb7ba85
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,42 @@ open class JavaTimeBaseTest : DatabaseTestsBase() {
}
}

@Test
fun testLocalDateTimeComparison() {
val testTableDT = object : IntIdTable("test_table_dt") {
val created = datetime("created")
val modified = datetime("modified")
}

withTables(testTableDT) { testDb ->
val mayTheFourthDT = LocalDateTime.of(2011, 5, 4, 13, 0, 21, 871130789)
val nowDT = LocalDateTime.now()
val id1 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = mayTheFourthDT
}
val id2 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = nowDT
}

// these DB take the nanosecond value 871_130_789 and round up to default precision (e.g. in Oracle: 871_131)
val requiresExplicitDTCast = listOf(TestDB.ORACLE, TestDB.H2_ORACLE, TestDB.H2_PSQL, TestDB.H2_SQLSERVER)
val dateTime = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(mayTheFourthDT), JavaLocalDateTimeColumnType())
else -> dateTimeParam(mayTheFourthDT)
}
val createdMayFourth = testTableDT.select { testTableDT.created eq dateTime }.count()
assertEquals(2, createdMayFourth)

val modifiedAtSameDT = testTableDT.select { testTableDT.modified eq testTableDT.created }.single()
assertEquals(id1, modifiedAtSameDT[testTableDT.id])

val modifiedAtLaterDT = testTableDT.select { testTableDT.modified greater testTableDT.created }.single()
assertEquals(id2, modifiedAtLaterDT[testTableDT.id])
}
}

@Test
fun testDateTimeAsJsonB() {
val tester = object : Table("tester") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
package org.jetbrains.exposed

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.javatime.date
import org.jetbrains.exposed.sql.javatime.datetime
import org.jetbrains.exposed.sql.javatime.duration
import org.jetbrains.exposed.sql.javatime.time
import org.jetbrains.exposed.sql.javatime.timestamp
import org.jetbrains.exposed.sql.javatime.*
import org.jetbrains.exposed.sql.tests.DatabaseTestsBase
import org.jetbrains.exposed.sql.tests.TestDB
import org.jetbrains.exposed.sql.tests.shared.MiscTable
Expand Down Expand Up @@ -252,10 +248,14 @@ class MiscTableTest : DatabaseTestsBase() {
}
}

// these DB take the datetime nanosecond value and round up to default precision
// which causes flaky comparison failures if not cast to TIMESTAMP first
private val requiresExplicitDTCast = listOf(TestDB.ORACLE, TestDB.H2_ORACLE, TestDB.H2_PSQL, TestDB.H2_SQLSERVER)

@Test
fun testSelect01() {
val tbl = Misc
withTables(tbl) {
withTables(tbl) { testDb ->
val date = today
val time = LocalTime.now()
val dateTime = LocalDateTime.now()
Expand Down Expand Up @@ -436,8 +436,12 @@ class MiscTableTest : DatabaseTestsBase() {
dblcn = null
)

val dtValue = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(dateTime), JavaLocalDateTimeColumnType())
else -> dateTimeParam(dateTime)
}
tbl.checkRowFull(
tbl.select { tbl.dt.eq(dateTime) }.single(),
tbl.select { tbl.dt.eq(dtValue) }.single(),
by = 13,
byn = null,
sm = -10,
Expand Down Expand Up @@ -692,7 +696,7 @@ class MiscTableTest : DatabaseTestsBase() {
@Test
fun testSelect02() {
val tbl = Misc
withTables(tbl) {
withTables(tbl) { testDb ->
val date = today
val time = LocalTime.now()
val dateTime = LocalDateTime.now()
Expand Down Expand Up @@ -858,8 +862,12 @@ class MiscTableTest : DatabaseTestsBase() {
dblcn = 567.89
)

val dtValue = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(dateTime), JavaLocalDateTimeColumnType())
else -> dateTimeParam(dateTime)
}
tbl.checkRowFull(
tbl.select { tbl.dt.eq(dateTime) }.single(),
tbl.select { tbl.dt.eq(dtValue) }.single(),
by = 13,
byn = 13,
sm = -10,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,36 @@ open class JodaTimeBaseTest : DatabaseTestsBase() {
}
}

@Test
fun testLocalDateTimeComparison() {
val testTableDT = object : IntIdTable("test_table_dt") {
val created = datetime("created")
val modified = datetime("modified")
}

withTables(testTableDT) {
val mayTheFourthDT = DateTime.parse("2011-05-04T13:00:21.871130789Z")
val nowDT = DateTime.now()
val id1 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = mayTheFourthDT
}
val id2 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = nowDT
}

val createdMayFourth = testTableDT.select { testTableDT.created eq dateTimeParam(mayTheFourthDT) }.count()
assertEquals(2, createdMayFourth)

val modifiedAtSameDT = testTableDT.select { testTableDT.modified eq testTableDT.created }.single()
assertEquals(id1, modifiedAtSameDT[testTableDT.id])

val modifiedAtLaterDT = testTableDT.select { testTableDT.modified greater testTableDT.created }.single()
assertEquals(id2, modifiedAtLaterDT[testTableDT.id])
}
}

@Test
fun testDateTimeAsJsonB() {
val tester = object : Table("tester") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,43 @@ open class KotlinTimeBaseTest : DatabaseTestsBase() {
}
}

@Test
fun testLocalDateTimeComparison() {
val testTableDT = object : IntIdTable("test_table_dt") {
val created = datetime("created")
val modified = datetime("modified")
}

withTables(testTableDT) { testDb ->
val mayTheFourth = "2011-05-04T13:00:21.871130789Z"
val mayTheFourthDT = Instant.parse(mayTheFourth).toLocalDateTime(TimeZone.currentSystemDefault())
val nowDT = now()
val id1 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = mayTheFourthDT
}
val id2 = testTableDT.insertAndGetId {
it[created] = mayTheFourthDT
it[modified] = nowDT
}

// these DB take the nanosecond value 871_130_789 and round up to default precision (e.g. in Oracle: 871_131)
val requiresExplicitDTCast = listOf(TestDB.ORACLE, TestDB.H2_ORACLE, TestDB.H2_PSQL, TestDB.H2_SQLSERVER)
val dateTime = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(mayTheFourthDT), KotlinLocalDateTimeColumnType())
else -> dateTimeParam(mayTheFourthDT)
}
val createdMayFourth = testTableDT.select { testTableDT.created eq dateTime }.count()
assertEquals(2, createdMayFourth)

val modifiedAtSameDT = testTableDT.select { testTableDT.modified eq testTableDT.created }.single()
assertEquals(id1, modifiedAtSameDT[testTableDT.id])

val modifiedAtLaterDT = testTableDT.select { testTableDT.modified greater testTableDT.created }.single()
assertEquals(id2, modifiedAtLaterDT[testTableDT.id])
}
}

@Test
fun testDateTimeAsJsonB() {
val tester = object : Table("tester") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,14 @@ class MiscTableTest : DatabaseTestsBase() {
}
}

// these DB take the datetime nanosecond value and round up to default precision
// which causes flaky comparison failures if not cast to TIMESTAMP first
private val requiresExplicitDTCast = listOf(TestDB.ORACLE, TestDB.H2_ORACLE, TestDB.H2_PSQL, TestDB.H2_SQLSERVER)

@Test
fun testSelect01() {
val tbl = Misc
withTables(tbl) {
withTables(tbl) { testDb ->
val date = today
val dateTime = now()
val time = dateTime.time
Expand Down Expand Up @@ -436,8 +440,12 @@ class MiscTableTest : DatabaseTestsBase() {
dblcn = null
)

val dtValue = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(dateTime), KotlinLocalDateTimeColumnType())
else -> dateTimeParam(dateTime)
}
tbl.checkRowFull(
tbl.select { tbl.dt.eq(dateTime) }.single(),
tbl.select { tbl.dt.eq(dtValue) }.single(),
by = 13,
byn = null,
sm = -10,
Expand Down Expand Up @@ -692,7 +700,7 @@ class MiscTableTest : DatabaseTestsBase() {
@Test
fun testSelect02() {
val tbl = Misc
withTables(tbl) {
withTables(tbl) { testDb ->
val date = today
val dateTime = now()
val time = dateTime.time
Expand Down Expand Up @@ -858,8 +866,12 @@ class MiscTableTest : DatabaseTestsBase() {
dblcn = 567.89
)

val dtValue = when (testDb) {
in requiresExplicitDTCast -> Cast(dateTimeParam(dateTime), KotlinLocalDateTimeColumnType())
else -> dateTimeParam(dateTime)
}
tbl.checkRowFull(
tbl.select { tbl.dt.eq(dateTime) }.single(),
tbl.select { tbl.dt.eq(dtValue) }.single(),
by = 13,
byn = 13,
sm = -10,
Expand Down

0 comments on commit bb7ba85

Please sign in to comment.