diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 10acfd9dda..2b8097d979 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -160,6 +160,7 @@ public final class org/jetbrains/exposed/sql/ArrayColumnType : org/jetbrains/exp public final fun getDelegate ()Lorg/jetbrains/exposed/sql/ColumnType; public final fun getDelegateType ()Ljava/lang/String; public final fun getMaximumCardinality ()Ljava/lang/Integer; + 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 readObject (Ljava/sql/ResultSet;I)Ljava/lang/Object; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt index 607e8b6457..6ec59147c4 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/ColumnType.kt @@ -1085,6 +1085,15 @@ class ArrayColumnType( else -> super.nonNullValueToString(value) } + override fun nonNullValueAsDefaultString(value: Any): String = when (value) { + is List<*> -> { + val prefix = if (currentDialect is H2Dialect) "ARRAY [" else "ARRAY[" + value.joinToString(",", prefix, "]") { delegate.valueAsDefaultString(it) } + } + is Array<*> -> nonNullValueAsDefaultString(value.toList()) + else -> super.nonNullValueAsDefaultString(value) + } + override fun readObject(rs: ResultSet, index: Int): Any? = rs.getArray(index) override fun setParameter(stmt: PreparedStatementApi, index: Int, value: Any?) { 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 0dcf477ae3..0f545c1367 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 @@ -18,6 +18,7 @@ import org.jetbrains.exposed.sql.json.jsonb import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.TestDB import org.jetbrains.exposed.sql.tests.currentDialectTest +import org.jetbrains.exposed.sql.tests.shared.assertEqualLists import org.jetbrains.exposed.sql.tests.shared.assertEquals import org.jetbrains.exposed.sql.tests.shared.assertTrue import org.jetbrains.exposed.sql.tests.shared.expectException @@ -472,6 +473,38 @@ open class JavaTimeBaseTest : DatabaseTestsBase() { currentDbDateTime() } } + + @Test + fun testDateTimeAsArray() { + val defaultDates = listOf(today) + val defaultDateTimes = listOf(LocalDateTime.now()) + val tester = object : Table("array_tester") { + val dates = array("dates", JavaLocalDateColumnType()).default(defaultDates) + val datetimes = array("datetimes", JavaLocalDateTimeColumnType()).default(defaultDateTimes) + } + + withTables(excludeSettings = TestDB.entries - TestDB.POSTGRESQL - TestDB.H2, tester) { + tester.insert { } + val result1 = tester.selectAll().single() + assertEqualLists(result1[tester.dates], defaultDates) + assertEqualLists(result1[tester.datetimes], defaultDateTimes) + + val datesInput = List(3) { LocalDate.of(2020 + it, 5, 4) } + val datetimeInput = List(3) { LocalDateTime.of(2020 + it, 5, 4, 9, 9, 9) } + tester.insert { + it[dates] = datesInput + it[datetimes] = datetimeInput + } + + val lastDate = tester.dates[3] + val firstTwoDatetimes = tester.datetimes.slice(1, 2) + val result2 = tester.select(lastDate, firstTwoDatetimes).where { + tester.dates[1].year() eq 2020 + }.single() + assertEqualDateTime(datesInput.last(), result2[lastDate]) + assertEqualLists(result2[firstTwoDatetimes], datetimeInput.take(2)) + } + } } fun assertEqualDateTime(d1: T?, d2: T?) { diff --git a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeTests.kt b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeTests.kt index 2b50c8280d..5c86b31186 100644 --- a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeTests.kt +++ b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeTests.kt @@ -17,6 +17,7 @@ import org.jetbrains.exposed.sql.json.jsonb import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.TestDB import org.jetbrains.exposed.sql.tests.currentDialectTest +import org.jetbrains.exposed.sql.tests.shared.assertEqualLists import org.jetbrains.exposed.sql.tests.shared.assertEquals import org.jetbrains.exposed.sql.tests.shared.assertTrue import org.jetbrains.exposed.sql.tests.shared.expectException @@ -370,6 +371,39 @@ open class JodaTimeBaseTest : DatabaseTestsBase() { currentDbDateTime() } } + + @Test + fun testDateTimeAsArray() { + val defaultDates = listOf(today) + val defaultDateTimes = listOf(DateTime.now()) + val tester = object : Table("array_tester") { + val dates = array("dates", DateColumnType(false)).default(defaultDates) + val datetimes = array("datetimes", DateColumnType(true)).default(defaultDateTimes) + } + + withTables(excludeSettings = TestDB.entries - TestDB.POSTGRESQL - TestDB.H2, tester) { + addLogger(StdOutSqlLogger) + tester.insert { } + val result1 = tester.selectAll().single() + assertEqualLists(result1[tester.dates], defaultDates) + assertEqualLists(result1[tester.datetimes], defaultDateTimes) + + val datesInput = List(3) { DateTime.parse("${2020 + it}-5-4") } + val datetimeInput = List(3) { DateTime(2020 + it, 5, 4, 9, 9, 9) } + tester.insert { + it[dates] = datesInput + it[datetimes] = datetimeInput + } + + val lastDate = tester.dates[3] + val firstTwoDatetimes = tester.datetimes.slice(1, 2) + val result2 = tester.select(lastDate, firstTwoDatetimes).where { + tester.dates[1].year() eq 2020 + }.single() + assertEqualDateTime(datesInput.last(), result2[lastDate]) + assertEqualLists(result2[firstTwoDatetimes], datetimeInput.take(2)) + } + } } fun assertEqualDateTime(d1: DateTime?, d2: DateTime?) { diff --git a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/KotlinTimeTests.kt b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/KotlinTimeTests.kt index 37cdf0de63..d7ea86c6b1 100644 --- a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/KotlinTimeTests.kt +++ b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/KotlinTimeTests.kt @@ -14,6 +14,7 @@ import org.jetbrains.exposed.sql.json.jsonb import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.TestDB import org.jetbrains.exposed.sql.tests.currentDialectTest +import org.jetbrains.exposed.sql.tests.shared.assertEqualLists import org.jetbrains.exposed.sql.tests.shared.assertEquals import org.jetbrains.exposed.sql.tests.shared.assertTrue import org.jetbrains.exposed.sql.tests.shared.expectException @@ -479,6 +480,38 @@ open class KotlinTimeBaseTest : DatabaseTestsBase() { assertEquals(Duration.INFINITE, row[tester.duration]) } } + + @Test + fun testDateTimeAsArray() { + val defaultDates = listOf(now().date) + val defaultDateTimes = listOf(now()) + val tester = object : Table("array_tester") { + val dates = array("dates", KotlinLocalDateColumnType()).default(defaultDates) + val datetimes = array("datetimes", KotlinLocalDateTimeColumnType()).default(defaultDateTimes) + } + + withTables(excludeSettings = TestDB.entries - TestDB.POSTGRESQL - TestDB.H2, tester) { + tester.insert { } + val result1 = tester.selectAll().single() + assertEqualLists(result1[tester.dates], defaultDates) + assertEqualLists(result1[tester.datetimes], defaultDateTimes) + + val datesInput = List(3) { LocalDate(2020 + it, 5, 4) } + val datetimeInput = List(3) { LocalDateTime(2020 + it, 5, 4, 9, 9, 9) } + tester.insert { + it[dates] = datesInput + it[datetimes] = datetimeInput + } + + val lastDate = tester.dates[3] + val firstTwoDatetimes = tester.datetimes.slice(1, 2) + val result2 = tester.select(lastDate, firstTwoDatetimes).where { + tester.dates[1].year() eq 2020 + }.single() + assertEqualDateTime(datesInput.last(), result2[lastDate]) + assertEqualLists(result2[firstTwoDatetimes], datetimeInput.take(2)) + } + } } fun assertEqualDateTime(d1: T?, d2: T?) {