Skip to content
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-384 CurrentTimestamp cannot be used with OffsetDateTimeColumnType #2081

Merged
merged 2 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions exposed-java-time/api/exposed-java-time.api
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ public final class org/jetbrains/exposed/sql/javatime/CurrentDate : org/jetbrain
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/javatime/CurrentDateTime : org/jetbrains/exposed/sql/Function {
public final class org/jetbrains/exposed/sql/javatime/CurrentDateTime : org/jetbrains/exposed/sql/javatime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/javatime/CurrentDateTime;
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/javatime/CurrentTimestamp : org/jetbrains/exposed/sql/Function {
public final class org/jetbrains/exposed/sql/javatime/CurrentTimestamp : org/jetbrains/exposed/sql/javatime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/javatime/CurrentTimestamp;
}

public abstract class org/jetbrains/exposed/sql/javatime/CurrentTimestampBase : org/jetbrains/exposed/sql/Function {
public synthetic fun <init> (Lorg/jetbrains/exposed/sql/IColumnType;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/javatime/CurrentTimestampWithTimeZone : org/jetbrains/exposed/sql/javatime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/javatime/CurrentTimestampWithTimeZone;
}

public final class org/jetbrains/exposed/sql/javatime/Date : org/jetbrains/exposed/sql/Function {
public fun <init> (Lorg/jetbrains/exposed/sql/Expression;)V
public final fun getExpr ()Lorg/jetbrains/exposed/sql/Expression;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ class Time<T : Temporal?>(val expr: Expression<T>) : Function<LocalTime>(JavaLoc
}

/**
* Represents an SQL function that returns the current date and time, as [LocalDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
* Represents the base SQL function that returns the current date and time, as determined by the specified [columnType].
*/
object CurrentDateTime : Function<LocalDateTime>(JavaLocalDateTimeColumnType.INSTANCE) {
sealed class CurrentTimestampBase<T>(columnType: IColumnType<T & Any>) : Function<T>(columnType) {
override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder {
+when {
(currentDialect as? MysqlDialect)?.isFractionDateTimeSupported() == true -> "CURRENT_TIMESTAMP(6)"
Expand All @@ -54,19 +52,26 @@ object CurrentDate : Function<LocalDate>(JavaLocalDateColumnType.INSTANCE) {
}
}

/**
* Represents an SQL function that returns the current date and time, as [LocalDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
*/
object CurrentDateTime : CurrentTimestampBase<LocalDateTime>(JavaLocalDateTimeColumnType.INSTANCE)

/**
* Represents an SQL function that returns the current date and time, as [Instant].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
*/
object CurrentTimestamp : Function<Instant>(JavaInstantColumnType.INSTANCE) {
override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder {
+when {
(currentDialect as? MysqlDialect)?.isFractionDateTimeSupported() == true -> "CURRENT_TIMESTAMP(6)"
else -> "CURRENT_TIMESTAMP"
}
}
}
object CurrentTimestamp : CurrentTimestampBase<Instant>(JavaInstantColumnType.INSTANCE)

/**
* Represents an SQL function that returns the current date and time with time zone, as [OffsetDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testTimestampWithTimeZoneDefaults
*/
object CurrentTimestampWithTimeZone : CurrentTimestampBase<OffsetDateTime>(JavaOffsetDateTimeColumnType.INSTANCE)

/** Represents an SQL function that extracts the year field from a given temporal [expr]. */
class Year<T : Temporal?>(val expr: Expression<T>) : Function<Int>(IntegerColumnType()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class DefaultsTest : DatabaseTestsBase() {
val testTable = object : IntIdTable("t") {
val t1 = timestampWithTimeZone("t1").default(nowWithTimeZone)
val t2 = timestampWithTimeZone("t2").defaultExpression(timestampWithTimeZoneLiteral)
val t3 = timestampWithTimeZone("t3").defaultExpression(CurrentTimestampWithTimeZone)
}

fun Expression<*>.itOrNull() = when {
Expand All @@ -425,7 +426,8 @@ class DefaultsTest : DatabaseTestsBase() {
"${"t".inProperCase()} (" +
"${"id".inProperCase()} ${currentDialectTest.dataTypeProvider.integerAutoincType()} PRIMARY KEY, " +
"${"t1".inProperCase()} $timestampWithTimeZoneType${testTable.t1.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}" +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" +
")"

val expected = if (currentDialectTest is OracleDialect ||
Expand All @@ -446,6 +448,9 @@ class DefaultsTest : DatabaseTestsBase() {
val row1 = testTable.selectAll().where { testTable.id eq id1 }.single()
assertEqualDateTime(nowWithTimeZone, row1[testTable.t1])
assertEqualDateTime(nowWithTimeZone, row1[testTable.t2])
val dbDefault = row1[testTable.t3]
assertEquals(dbDefault.offset, nowWithTimeZone.offset)
assertTrue { dbDefault.toLocalDateTime() >= nowWithTimeZone.toLocalDateTime() }

SchemaUtils.drop(testTable)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import org.joda.time.DateTimeZone
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

class JodaTimeDefaultsTest : JodaTimeBaseTest() {
object TableWithDBDefault : IntIdTable() {
Expand Down Expand Up @@ -375,6 +376,7 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() {
val testTable = object : IntIdTable("t") {
val t1 = timestampWithTimeZone("t1").default(nowWithTimeZone)
val t2 = timestampWithTimeZone("t2").defaultExpression(timestampWithTimeZoneLiteral)
val t3 = timestampWithTimeZone("t3").defaultExpression(CurrentDateTime)
}

fun Expression<*>.itOrNull() = when {
Expand All @@ -394,7 +396,8 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() {
"${"t".inProperCase()} (" +
"${"id".inProperCase()} ${currentDialectTest.dataTypeProvider.integerAutoincType()} PRIMARY KEY, " +
"${"t1".inProperCase()} $timestampWithTimeZoneType${testTable.t1.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}" +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentDateTime.itOrNull()}" +
")"

val expected = if (currentDialectTest is OracleDialect ||
Expand All @@ -415,6 +418,7 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() {
val row1 = testTable.selectAll().where { testTable.id eq id1 }.single()
assertEqualDateTime(nowWithTimeZone, row1[testTable.t1])
assertEqualDateTime(nowWithTimeZone, row1[testTable.t2])
assertTrue { row1[testTable.t3].millis >= nowWithTimeZone.millis }

SchemaUtils.drop(testTable)
}
Expand Down
13 changes: 10 additions & 3 deletions exposed-kotlin-datetime/api/exposed-kotlin-datetime.api
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentDate : org/j
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentDateTime : org/jetbrains/exposed/sql/Function {
public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentDateTime : org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/kotlin/datetime/CurrentDateTime;
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestamp : org/jetbrains/exposed/sql/Function {
public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestamp : org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestamp;
}

public abstract class org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampBase : org/jetbrains/exposed/sql/Function {
public synthetic fun <init> (Lorg/jetbrains/exposed/sql/IColumnType;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun toQueryBuilder (Lorg/jetbrains/exposed/sql/QueryBuilder;)V
}

public final class org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampWithTimeZone : org/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampBase {
public static final field INSTANCE Lorg/jetbrains/exposed/sql/kotlin/datetime/CurrentTimestampWithTimeZone;
}

public final class org/jetbrains/exposed/sql/kotlin/datetime/KotlinDateColumnTypeKt {
public static final fun date (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
public static final fun datetime (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;)Lorg/jetbrains/exposed/sql/Column;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,9 @@ fun <T : LocalDateTime?> Time(expr: Expression<T>): Function<LocalTime> = TimeFu
fun <T : Instant?> Time(expr: Expression<T>): Function<LocalTime> = TimeFunction(expr)

/**
* Represents an SQL function that returns the current date and time, as [LocalDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
* Represents the base SQL function that returns the current date and time, as determined by the specified [columnType].
*/
object CurrentDateTime : Function<LocalDateTime>(KotlinLocalDateTimeColumnType.INSTANCE) {
sealed class CurrentTimestampBase<T>(columnType: IColumnType<T & Any>) : Function<T>(columnType) {
override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder {
+when {
(currentDialect as? MysqlDialect)?.isFractionDateTimeSupported() == true -> "CURRENT_TIMESTAMP(6)"
Expand All @@ -62,6 +60,27 @@ object CurrentDateTime : Function<LocalDateTime>(KotlinLocalDateTimeColumnType.I
}
}

/**
* Represents an SQL function that returns the current date and time, as [LocalDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
*/
object CurrentDateTime : CurrentTimestampBase<LocalDateTime>(KotlinLocalDateTimeColumnType.INSTANCE)

/**
* Represents an SQL function that returns the current date and time, as [Instant].
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
*/
object CurrentTimestamp : CurrentTimestampBase<Instant>(KotlinInstantColumnType.INSTANCE)

/**
* Represents an SQL function that returns the current date and time with time zone, as [OffsetDateTime].
*
* @sample org.jetbrains.exposed.DefaultsTest.testTimestampWithTimeZoneDefaults
*/
object CurrentTimestampWithTimeZone : CurrentTimestampBase<OffsetDateTime>(KotlinOffsetDateTimeColumnType.INSTANCE)

/**
* Represents an SQL function that returns the current date, as [LocalDate].
*
Expand All @@ -77,20 +96,6 @@ object CurrentDate : Function<LocalDate>(KotlinLocalDateColumnType.INSTANCE) {
}
}

/**
* Represents an SQL function that returns the current date and time.
*
* @sample org.jetbrains.exposed.DefaultsTest.testConsistentSchemeWithFunctionAsDefaultExpression
*/
object CurrentTimestamp : Function<Instant>(KotlinInstantColumnType.INSTANCE) {
override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder {
+when {
(currentDialect as? MysqlDialect)?.isFractionDateTimeSupported() == true -> "CURRENT_TIMESTAMP(6)"
else -> "CURRENT_TIMESTAMP"
}
}
}

class YearInternal(val expr: Expression<*>) : Function<Int>(IntegerColumnType()) {
override fun toQueryBuilder(queryBuilder: QueryBuilder) = queryBuilder {
val dialect = currentDialect
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ class DefaultsTest : DatabaseTestsBase() {
val testTable = object : IntIdTable("t") {
val t1 = timestampWithTimeZone("t1").default(nowWithTimeZone)
val t2 = timestampWithTimeZone("t2").defaultExpression(timestampWithTimeZoneLiteral)
val t3 = timestampWithTimeZone("t3").defaultExpression(CurrentTimestampWithTimeZone)
}

fun Expression<*>.itOrNull() = when {
Expand All @@ -429,7 +430,8 @@ class DefaultsTest : DatabaseTestsBase() {
"${"t".inProperCase()} (" +
"${"id".inProperCase()} ${currentDialectTest.dataTypeProvider.integerAutoincType()} PRIMARY KEY, " +
"${"t1".inProperCase()} $timestampWithTimeZoneType${testTable.t1.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}" +
"${"t2".inProperCase()} $timestampWithTimeZoneType${testTable.t2.constraintNamePart()} ${timestampWithTimeZoneLiteral.itOrNull()}, " +
"${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" +
")"

val expected = if (currentDialectTest is OracleDialect ||
Expand All @@ -450,6 +452,9 @@ class DefaultsTest : DatabaseTestsBase() {
val row1 = testTable.selectAll().where { testTable.id eq id1 }.single()
assertEqualDateTime(nowWithTimeZone, row1[testTable.t1])
assertEqualDateTime(nowWithTimeZone, row1[testTable.t2])
val dbDefault = row1[testTable.t3]
assertEquals(dbDefault.offset, nowWithTimeZone.offset)
assertTrue { dbDefault.toLocalDateTime().toKotlinLocalDateTime() >= nowWithTimeZone.toLocalDateTime().toKotlinLocalDateTime() }

SchemaUtils.drop(testTable)
}
Expand Down
Loading