From 6d838a1864eb103ef0a782951419f87da0b3c7d1 Mon Sep 17 00:00:00 2001 From: Oleg Babichev Date: Mon, 27 May 2024 11:50:00 +0200 Subject: [PATCH 1/5] fix: EXPOSED-277 statementsRequiredToActualizeScheme does not check sequences --- .../kotlin/org/jetbrains/exposed/sql/Table.kt | 25 +++++++++++-------- .../org/jetbrains/exposed/DefaultsTest.kt | 23 ++--------------- .../sql/tests/shared/ddl/SequencesTests.kt | 24 ++++++++++++++++++ 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt index 444c3c23c3..98fae9b9fd 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt @@ -1364,15 +1364,6 @@ open class Table(name: String = "") : ColumnSet(), DdlAware { } override fun createStatement(): List { - val createSequence = autoIncColumn?.autoIncColumnType?.autoincSeq?.let { - Sequence( - it, - startWith = 1, - minValue = 1, - maxValue = Long.MAX_VALUE - ).createStatement() - }.orEmpty() - val addForeignKeysInAlterPart = SchemaUtils.checkCycle(this) && currentDialect !is SQLiteDialect val foreignKeyConstraints = foreignKeys @@ -1422,7 +1413,21 @@ open class Table(name: String = "") : ColumnSet(), DdlAware { emptyList() } - return createSequence + createTable + createConstraint + return createAutoIncColumnSequence() + createTable + createConstraint + } + + private fun createAutoIncColumnSequence(): List { + return autoIncColumn?.autoIncColumnType?.autoincSeq?.let { + Sequence( + it, + startWith = 1, + minValue = 1, + maxValue = Long.MAX_VALUE + ) + } + ?.takeIf { !it.exists() } + ?.createStatement() + .orEmpty() } override fun modifyStatement(): List = diff --git a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt index 53015e6f28..0e4cbcf439 100644 --- a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt +++ b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt @@ -20,11 +20,9 @@ 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 -import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect -import org.jetbrains.exposed.sql.vendors.h2Mode import org.junit.Test import java.time.* import kotlin.test.assertEquals @@ -264,13 +262,7 @@ class DefaultsTest : DatabaseTestsBase() { "${"t10".inProperCase()} $timeType${testTable.t10.constraintNamePart()} ${tLiteral.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { - arrayListOf("CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", baseExpression) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -430,18 +422,7 @@ class DefaultsTest : DatabaseTestsBase() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || - currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle - ) { - arrayListOf( - "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", - baseExpression - ) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt index 2b01b05a03..763018fa94 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt @@ -13,6 +13,7 @@ import org.jetbrains.exposed.sql.tests.shared.assertTrue import org.jetbrains.exposed.sql.vendors.currentDialect import org.junit.Test import kotlin.test.assertNotNull +import kotlin.test.assertNull class SequencesTests : DatabaseTestsBase() { @Test @@ -198,6 +199,29 @@ class SequencesTests : DatabaseTestsBase() { } } + @Test + fun testABCDEF() { + withDb { + if (currentDialectTest.supportsSequenceAsGeneratedKeys) { + val createSequencePrefix = "CREATE SEQUENCE" + + assertNotNull(SchemaUtils.createStatements(DeveloperWithAutoIncrementBySequence).find { it.startsWith(createSequencePrefix) }) + + SchemaUtils.create(DeveloperWithAutoIncrementBySequence) + + // Remove table without removing sequence + exec("DROP TABLE ${DeveloperWithAutoIncrementBySequence.nameInDatabaseCase()}") + + assertNull(SchemaUtils.createStatements(DeveloperWithAutoIncrementBySequence).find { it.startsWith(createSequencePrefix) }) + assertNull(SchemaUtils.statementsRequiredToActualizeScheme(DeveloperWithAutoIncrementBySequence).find { it.startsWith(createSequencePrefix) }) + + // Clean up: create table and drop it for removing sequence + SchemaUtils.create(DeveloperWithAutoIncrementBySequence) + SchemaUtils.drop(DeveloperWithAutoIncrementBySequence) + } + } + } + private object Developer : Table() { val id = integer("id") var name = varchar("name", 25) From d81594119f203a7f682a422f8f798c04e1de95cf Mon Sep 17 00:00:00 2001 From: Oleg Babichev Date: Mon, 27 May 2024 14:15:46 +0200 Subject: [PATCH 2/5] Fix broken tests --- .../jetbrains/exposed/JodaTimeDefaultsTest.kt | 26 ++----------------- .../sql/kotlin/datetime/DefaultsTest.kt | 23 ++-------------- 2 files changed, 4 insertions(+), 45 deletions(-) diff --git a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt index 7bf7540dfa..b6e9a858e3 100644 --- a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt +++ b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt @@ -19,12 +19,10 @@ 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 -import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect import org.jetbrains.exposed.sql.vendors.currentDialect -import org.jetbrains.exposed.sql.vendors.h2Mode import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.junit.Test @@ -194,16 +192,7 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() { "${"t4".inProperCase()} DATE${testTable.t4.constraintNamePart()} ${dtLiteral.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { - arrayListOf( - "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", - baseExpression - ) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -400,18 +389,7 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentDateTime.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || - currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle - ) { - arrayListOf( - "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", - baseExpression - ) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } diff --git a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt index 26699eca39..325a367a08 100644 --- a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt +++ b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt @@ -20,11 +20,9 @@ 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 -import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect -import org.jetbrains.exposed.sql.vendors.h2Mode import org.junit.Test import java.time.OffsetDateTime import java.time.ZoneId @@ -262,13 +260,7 @@ class DefaultsTest : DatabaseTestsBase() { "${"t10".inProperCase()} $timeType${testTable.t10.constraintNamePart()} ${tLiteral.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { - arrayListOf("CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", baseExpression) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -434,18 +426,7 @@ class DefaultsTest : DatabaseTestsBase() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" + ")" - val expected = if (currentDialectTest is OracleDialect || - currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle - ) { - arrayListOf( - "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", - baseExpression - ) - } else { - arrayListOf(baseExpression) - } - - assertEqualLists(expected, testTable.ddl) + assertEqualLists(arrayListOf(baseExpression), testTable.ddl) val id1 = testTable.insertAndGetId { } From e0ae9149750f77eab30541307e9399f33448002b Mon Sep 17 00:00:00 2001 From: Oleg Babichev Date: Mon, 27 May 2024 14:53:43 +0200 Subject: [PATCH 3/5] Fix CreateTableTests --- .../sql/tests/shared/ddl/CreateTableTests.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/CreateTableTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/CreateTableTests.kt index f11c798974..8d7c1247ca 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/CreateTableTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/CreateTableTests.kt @@ -305,7 +305,7 @@ class CreateTableTests : DatabaseTestsBase() { fkName = fkName ) } - withTables(parent, child) { + withDb { val t = TransactionManager.current() val expected = listOfNotNull( child.autoIncColumn?.autoIncColumnType?.autoincSeq?.let { @@ -338,7 +338,7 @@ class CreateTableTests : DatabaseTestsBase() { onDelete = ReferenceOption.NO_ACTION, ) } - withTables(parent, child) { + withDb { val expected = "CREATE TABLE " + addIfNotExistsIfSupported() + "${this.identity(child)} (" + "${child.columns.joinToString { it.descriptionDdl(false) }}," + " CONSTRAINT ${"fk_Child_parent_id__id".inProperCase()}" + @@ -360,7 +360,7 @@ class CreateTableTests : DatabaseTestsBase() { onDelete = ReferenceOption.NO_ACTION, ) } - withTables(parent, child) { + withDb { val expected = "CREATE TABLE " + addIfNotExistsIfSupported() + "${this.identity(child)} (" + "${child.columns.joinToString { it.descriptionDdl(false) }}," + " CONSTRAINT ${"fk_Child2_parent_id__id".inProperCase()}" + @@ -386,7 +386,7 @@ class CreateTableTests : DatabaseTestsBase() { fkName = fkName ) } - withTables(parent, child) { + withDb { val t = TransactionManager.current() val expected = listOfNotNull( child.autoIncColumn?.autoIncColumnType?.autoincSeq?.let { @@ -421,7 +421,7 @@ class CreateTableTests : DatabaseTestsBase() { fkName = fkName ) } - withTables(parent, child) { + withDb { val t = TransactionManager.current() val expected = listOfNotNull( child.autoIncColumn?.autoIncColumnType?.autoincSeq?.let { @@ -459,7 +459,7 @@ class CreateTableTests : DatabaseTestsBase() { fkName = fkName ) } - withTables(parent, child) { + withDb { val t = TransactionManager.current() val expected = listOfNotNull( child.autoIncColumn?.autoIncColumnType?.autoincSeq?.let { @@ -503,7 +503,7 @@ class CreateTableTests : DatabaseTestsBase() { ) } } - withTables(parent, child) { testDb -> + withDb { testDb -> val t = TransactionManager.current() val updateCascadePart = if (testDb != TestDB.ORACLE) " ON UPDATE CASCADE" else "" val expected = listOfNotNull( @@ -550,7 +550,7 @@ class CreateTableTests : DatabaseTestsBase() { ) } } - withTables(parent, child) { + withDb { val t = TransactionManager.current() val expected = listOfNotNull( child.autoIncColumn?.autoIncColumnType?.autoincSeq?.let { From 1e80a66bfdfd7325468b7e0142f14c8d3269d274 Mon Sep 17 00:00:00 2001 From: Oleg Babichev Date: Mon, 3 Jun 2024 10:53:52 +0200 Subject: [PATCH 4/5] Check for existing sequence inside SchemaUtils instead of Table class --- exposed-core/api/exposed-core.api | 12 +++++++-- .../org/jetbrains/exposed/sql/Column.kt | 3 --- .../org/jetbrains/exposed/sql/Constraints.kt | 3 +++ .../org/jetbrains/exposed/sql/SchemaUtils.kt | 19 +++++++++++++- .../kotlin/org/jetbrains/exposed/sql/Table.kt | 4 --- .../org/jetbrains/exposed/DefaultsTest.kt | 23 ++++++++++++++-- .../jetbrains/exposed/JodaTimeDefaultsTest.kt | 26 +++++++++++++++++-- .../sql/kotlin/datetime/DefaultsTest.kt | 23 ++++++++++++++-- .../sql/tests/shared/ddl/SequencesTests.kt | 2 +- 9 files changed, 98 insertions(+), 17 deletions(-) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 745fbc89b1..c817412585 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -368,6 +368,7 @@ public final class org/jetbrains/exposed/sql/CheckConstraint : org/jetbrains/exp public fun equals (Ljava/lang/Object;)Z public final fun getCheckName ()Ljava/lang/String; public final fun getCheckOp ()Ljava/lang/String; + public fun getDdl ()Ljava/util/List; public final fun getTableName ()Ljava/lang/String; public fun hashCode ()I public fun modifyStatement ()Ljava/util/List; @@ -393,7 +394,7 @@ public final class org/jetbrains/exposed/sql/Column : org/jetbrains/exposed/sql/ public fun dropStatement ()Ljava/util/List; public fun equals (Ljava/lang/Object;)Z public fun getColumnType ()Lorg/jetbrains/exposed/sql/IColumnType; - public final fun getDdl ()Ljava/util/List; + public fun getDdl ()Ljava/util/List; public final fun getDefaultValueFun ()Lkotlin/jvm/functions/Function0; public final fun getForeignKey ()Lorg/jetbrains/exposed/sql/ForeignKeyConstraint; public final fun getName ()Ljava/lang/String; @@ -707,9 +708,14 @@ public final class org/jetbrains/exposed/sql/DatabaseKt { public abstract interface class org/jetbrains/exposed/sql/DdlAware { public abstract fun createStatement ()Ljava/util/List; public abstract fun dropStatement ()Ljava/util/List; + public abstract fun getDdl ()Ljava/util/List; public abstract fun modifyStatement ()Ljava/util/List; } +public final class org/jetbrains/exposed/sql/DdlAware$DefaultImpls { + public static fun getDdl (Lorg/jetbrains/exposed/sql/DdlAware;)Ljava/util/List; +} + public final class org/jetbrains/exposed/sql/DecimalColumnType : org/jetbrains/exposed/sql/ColumnType { public static final field Companion Lorg/jetbrains/exposed/sql/DecimalColumnType$Companion; public fun (II)V @@ -933,6 +939,7 @@ public final class org/jetbrains/exposed/sql/ForeignKeyConstraint : org/jetbrain public fun dropStatement ()Ljava/util/List; public fun equals (Ljava/lang/Object;)Z public final fun getCustomFkName ()Ljava/lang/String; + public fun getDdl ()Ljava/util/List; public final fun getDeleteRule ()Lorg/jetbrains/exposed/sql/ReferenceOption; public final fun getFkName ()Ljava/lang/String; public final fun getFrom ()Ljava/util/LinkedHashSet; @@ -1272,6 +1279,7 @@ public final class org/jetbrains/exposed/sql/Index : org/jetbrains/exposed/sql/D public fun equals (Ljava/lang/Object;)Z public final fun getColumns ()Ljava/util/List; public final fun getCustomName ()Ljava/lang/String; + public fun getDdl ()Ljava/util/List; public final fun getFilterCondition ()Lorg/jetbrains/exposed/sql/Op; public final fun getFunctions ()Ljava/util/List; public final fun getFunctionsTable ()Lorg/jetbrains/exposed/sql/Table; @@ -2353,7 +2361,7 @@ public class org/jetbrains/exposed/sql/Table : org/jetbrains/exposed/sql/ColumnS public fun fullJoin (Lorg/jetbrains/exposed/sql/ColumnSet;)Lorg/jetbrains/exposed/sql/Join; public final fun getAutoIncColumn ()Lorg/jetbrains/exposed/sql/Column; public fun getColumns ()Ljava/util/List; - public final fun getDdl ()Ljava/util/List; + public fun getDdl ()Ljava/util/List; public final fun getForeignKeys ()Ljava/util/List; public final fun getIndices ()Ljava/util/List; public fun getPrimaryKey ()Lorg/jetbrains/exposed/sql/Table$PrimaryKey; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Column.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Column.kt index c585a4a141..b4dc676528 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Column.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Column.kt @@ -49,9 +49,6 @@ class Column( /** Appends the SQL representation of this column to the specified [queryBuilder]. */ override fun toQueryBuilder(queryBuilder: QueryBuilder): Unit = TransactionManager.current().fullIdentity(this@Column, queryBuilder) - /** Returns the list of DDL statements that create this column. */ - val ddl: List get() = createStatement() - /** Returns the column name in proper case. */ fun nameInDatabaseCase(): String = name.inProperCase() diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Constraints.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Constraints.kt index d70ca30236..76598f536c 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Constraints.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Constraints.kt @@ -20,6 +20,9 @@ interface DdlAware { /** Returns the list of DDL statements that drops this object. */ fun dropStatement(): List + + /** Returns the list of DDL statements that create this DdlAware instance. */ + val ddl: List get() = createStatement() } /** diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt index de94fc40f2..9885f6242c 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt @@ -102,13 +102,26 @@ object SchemaUtils { val toCreate = sortTablesByReferences(tables.toList()).filterNot { it.exists() } val alters = arrayListOf() return toCreate.flatMap { table -> - val (create, alter) = table.ddl.partition { it.startsWith("CREATE ") } + val (create, alter) = tableDdlWithoutExistingSequence(table).partition { it.startsWith("CREATE ") } val indicesDDL = table.indices.flatMap { createIndex(it) } alters += alter create + indicesDDL } + alters } + private fun tableDdlWithoutExistingSequence(table: Table): List { + val autoIncSeq = table.autoIncColumn?.autoIncColumnType?.autoincSeq + val sequenceExists = autoIncSeq?.let { currentDialect.sequenceExists(Sequence(it)) } ?: false + + return table.ddl.filter { statement -> + if (sequenceExists && autoIncSeq != null) { + !statement.lowercase().startsWith("create sequence") || !statement.contains(autoIncSeq) + } else { + true + } + } + } + /** Creates the provided sequences, using a batch execution if [inBatch] is set to `true`. */ fun createSequence(vararg seq: Sequence, inBatch: Boolean = false) { with(TransactionManager.current()) { @@ -199,11 +212,13 @@ object SchemaUtils { processed } } + is MariaDBDialect -> processed.trim('\'') is MysqlDialect -> "_utf8mb4\\'${processed.trim('(', ')', '\'')}\\" else -> processed.trim('\'') } } + column.columnType is ArrayColumnType<*> && dialect is PostgreSQLDialect -> { (value as List<*>) .takeIf { it.isNotEmpty() } @@ -220,6 +235,7 @@ object SchemaUtils { "ARRAY$processed" } ?: processForDefaultValue(exp) } + column.columnType is IDateColumnType -> { val processed = processForDefaultValue(exp) if (processed.startsWith('\'') && processed.endsWith('\'')) { @@ -228,6 +244,7 @@ object SchemaUtils { processed } } + else -> processForDefaultValue(exp) } } diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt index 98fae9b9fd..f5c0cdcb83 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Table.kt @@ -1351,9 +1351,6 @@ open class Table(name: String = "") : ColumnSet(), DdlAware { // DDL statements - /** Returns the list of DDL statements that create this table. */ - val ddl: List get() = createStatement() - internal fun primaryKeyConstraint(): String? { return primaryKey?.let { primaryKey -> val tr = TransactionManager.current() @@ -1425,7 +1422,6 @@ open class Table(name: String = "") : ColumnSet(), DdlAware { maxValue = Long.MAX_VALUE ) } - ?.takeIf { !it.exists() } ?.createStatement() .orEmpty() } diff --git a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt index 0e4cbcf439..53015e6f28 100644 --- a/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt +++ b/exposed-java-time/src/test/kotlin/org/jetbrains/exposed/DefaultsTest.kt @@ -20,9 +20,11 @@ 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 +import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect +import org.jetbrains.exposed.sql.vendors.h2Mode import org.junit.Test import java.time.* import kotlin.test.assertEquals @@ -262,7 +264,13 @@ class DefaultsTest : DatabaseTestsBase() { "${"t10".inProperCase()} $timeType${testTable.t10.constraintNamePart()} ${tLiteral.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { + arrayListOf("CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", baseExpression) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -422,7 +430,18 @@ class DefaultsTest : DatabaseTestsBase() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || + currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle + ) { + arrayListOf( + "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", + baseExpression + ) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } diff --git a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt index b6e9a858e3..7bf7540dfa 100644 --- a/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt +++ b/exposed-jodatime/src/test/kotlin/org/jetbrains/exposed/JodaTimeDefaultsTest.kt @@ -19,10 +19,12 @@ 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 +import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect import org.jetbrains.exposed.sql.vendors.currentDialect +import org.jetbrains.exposed.sql.vendors.h2Mode import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.junit.Test @@ -192,7 +194,16 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() { "${"t4".inProperCase()} DATE${testTable.t4.constraintNamePart()} ${dtLiteral.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { + arrayListOf( + "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", + baseExpression + ) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -389,7 +400,18 @@ class JodaTimeDefaultsTest : JodaTimeBaseTest() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentDateTime.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || + currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle + ) { + arrayListOf( + "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", + baseExpression + ) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } diff --git a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt index 325a367a08..26699eca39 100644 --- a/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt +++ b/exposed-kotlin-datetime/src/test/kotlin/org/jetbrains/exposed/sql/kotlin/datetime/DefaultsTest.kt @@ -20,9 +20,11 @@ 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 +import org.jetbrains.exposed.sql.vendors.H2Dialect import org.jetbrains.exposed.sql.vendors.MysqlDialect import org.jetbrains.exposed.sql.vendors.OracleDialect import org.jetbrains.exposed.sql.vendors.SQLServerDialect +import org.jetbrains.exposed.sql.vendors.h2Mode import org.junit.Test import java.time.OffsetDateTime import java.time.ZoneId @@ -260,7 +262,13 @@ class DefaultsTest : DatabaseTestsBase() { "${"t10".inProperCase()} $timeType${testTable.t10.constraintNamePart()} ${tLiteral.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle) { + arrayListOf("CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", baseExpression) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } @@ -426,7 +434,18 @@ class DefaultsTest : DatabaseTestsBase() { "${"t3".inProperCase()} $timestampWithTimeZoneType${testTable.t3.constraintNamePart()} ${CurrentTimestampWithTimeZone.itOrNull()}" + ")" - assertEqualLists(arrayListOf(baseExpression), testTable.ddl) + val expected = if (currentDialectTest is OracleDialect || + currentDialectTest.h2Mode == H2Dialect.H2CompatibilityMode.Oracle + ) { + arrayListOf( + "CREATE SEQUENCE t_id_seq START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807", + baseExpression + ) + } else { + arrayListOf(baseExpression) + } + + assertEqualLists(expected, testTable.ddl) val id1 = testTable.insertAndGetId { } diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt index 763018fa94..4191439697 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/SequencesTests.kt @@ -200,7 +200,7 @@ class SequencesTests : DatabaseTestsBase() { } @Test - fun testABCDEF() { + fun testNoCreateStatementForExistingSequence() { withDb { if (currentDialectTest.supportsSequenceAsGeneratedKeys) { val createSequencePrefix = "CREATE SEQUENCE" From 94d29b543a74b63d7dfa3e63933e044643cd26c6 Mon Sep 17 00:00:00 2001 From: Oleg Babichev Date: Tue, 11 Jun 2024 09:31:16 +0200 Subject: [PATCH 5/5] Review issue: simplify condition on filtering Create sequence statements --- .../main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt index 9885f6242c..e08ac731b4 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/SchemaUtils.kt @@ -110,12 +110,12 @@ object SchemaUtils { } private fun tableDdlWithoutExistingSequence(table: Table): List { - val autoIncSeq = table.autoIncColumn?.autoIncColumnType?.autoincSeq - val sequenceExists = autoIncSeq?.let { currentDialect.sequenceExists(Sequence(it)) } ?: false + val existingAutoIncSeq = table.autoIncColumn?.autoIncColumnType?.autoincSeq + ?.takeIf { currentDialect.sequenceExists(Sequence(it)) } return table.ddl.filter { statement -> - if (sequenceExists && autoIncSeq != null) { - !statement.lowercase().startsWith("create sequence") || !statement.contains(autoIncSeq) + if (existingAutoIncSeq != null) { + !statement.lowercase().startsWith("create sequence") || !statement.contains(existingAutoIncSeq) } else { true }