From 0f151196eccb8c12fa430f6a63748644f78814a5 Mon Sep 17 00:00:00 2001 From: Jocelyne Date: Mon, 27 Jan 2025 15:59:54 +0100 Subject: [PATCH] fix: EXPOSED-706 Handle MariaDB sequence max value for versions earlier than 11.5 According to the documentation [here](https://mariadb.com/kb/en/create-sequence/#maxvalue), MariaDB versions less than 11.5 have a max value for sequences that is lower than the one Exposed currently allows and that causes errors. --- exposed-core/api/exposed-core.api | 4 ++ .../org/jetbrains/exposed/sql/ColumnType.kt | 2 +- .../kotlin/org/jetbrains/exposed/sql/Table.kt | 2 +- .../exposed/sql/vendors/DatabaseDialect.kt | 2 + .../exposed/sql/vendors/MariaDBDialect.kt | 9 ++++ .../shared/ddl/DatabaseMigrationTests.kt | 44 ++++++++++++------- 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 3e58f5ce87..24d28707fb 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -3854,6 +3854,7 @@ public abstract interface class org/jetbrains/exposed/sql/vendors/DatabaseDialec public abstract fun getNeedsQuotesWhenSymbolsInNames ()Z public abstract fun getNeedsSequenceToAutoInc ()Z public abstract fun getRequiresAutoCommitOnCreateDrop ()Z + public abstract fun getSequenceMaxValue ()J public abstract fun getSupportsCreateSchema ()Z public abstract fun getSupportsCreateSequence ()Z public abstract fun getSupportsDualTableConcept ()Z @@ -3902,6 +3903,7 @@ public final class org/jetbrains/exposed/sql/vendors/DatabaseDialect$DefaultImpl public static fun getNeedsQuotesWhenSymbolsInNames (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z public static fun getNeedsSequenceToAutoInc (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z public static fun getRequiresAutoCommitOnCreateDrop (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z + public static fun getSequenceMaxValue (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)J public static fun getSupportsCreateSchema (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z public static fun getSupportsCreateSequence (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z public static fun getSupportsDualTableConcept (Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;)Z @@ -4163,6 +4165,7 @@ public final class org/jetbrains/exposed/sql/vendors/MariaDBDialect : org/jetbra public fun createIndex (Lorg/jetbrains/exposed/sql/Index;)Ljava/lang/String; public fun getFunctionProvider ()Lorg/jetbrains/exposed/sql/vendors/FunctionProvider; public fun getName ()Ljava/lang/String; + public fun getSequenceMaxValue ()J public fun getSupportsCreateSequence ()Z public fun getSupportsOnlyIdentifiersInGeneratedKeys ()Z public fun getSupportsSequenceAsGeneratedKeys ()Z @@ -4362,6 +4365,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/VendorDialect : org/jetb public fun getNeedsQuotesWhenSymbolsInNames ()Z public fun getNeedsSequenceToAutoInc ()Z public fun getRequiresAutoCommitOnCreateDrop ()Z + public fun getSequenceMaxValue ()J public fun getSupportsCreateSchema ()Z public fun getSupportsCreateSequence ()Z public fun getSupportsDualTableConcept ()Z 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 92002e22f8..141a3ee2fb 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 @@ -148,7 +148,7 @@ class AutoIncColumnType( it, startWith = 1, minValue = 1, - maxValue = Long.MAX_VALUE + maxValue = currentDialect.sequenceMaxValue ) } 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 529fab4933..01f19b99fc 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 @@ -516,7 +516,7 @@ open class Table(name: String = "") : ColumnSet(), DdlAware { fallbackSequenceName, startWith = 1, minValue = 1, - maxValue = Long.MAX_VALUE + maxValue = currentDialect.sequenceMaxValue ) } } diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/DatabaseDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/DatabaseDialect.kt index 8010d8a31d..665704cc45 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/DatabaseDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/DatabaseDialect.kt @@ -75,6 +75,8 @@ interface DatabaseDialect { /** Returns true if autoCommit should be enabled to create/drop a database. */ val requiresAutoCommitOnCreateDrop: Boolean get() = false + val sequenceMaxValue: Long get() = Long.MAX_VALUE + /** Returns the name of the current database. */ fun getDatabase(): String diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt index 86093dad04..63b5051e6b 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MariaDBDialect.kt @@ -78,6 +78,15 @@ class MariaDBDialect : MysqlDialect() { // actually MariaDb supports it but jdbc driver prepares statement without RETURNING clause override val supportsSequenceAsGeneratedKeys: Boolean = false + @Suppress("MagicNumber") + override val sequenceMaxValue: Long by lazy { + if (TransactionManager.current().db.isVersionCovers(11, 5)) { + super.sequenceMaxValue + } else { + Long.MAX_VALUE - 1 + } + } + override fun createIndex(index: Index): String { if (index.functions != null) { exposedLogger.warn( diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/DatabaseMigrationTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/DatabaseMigrationTests.kt index 75304b67b4..d44c08773f 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/DatabaseMigrationTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/ddl/DatabaseMigrationTests.kt @@ -25,9 +25,18 @@ import kotlin.test.assertNull @OptIn(ExperimentalDatabaseMigrationApi::class) class DatabaseMigrationTests : DatabaseTestsBase() { + private lateinit var sequence: Sequence + @Before fun dropAllSequences() { withDb { + sequence = Sequence( + name = "my_sequence", + startWith = 1, + minValue = 1, + maxValue = currentDialectTest.sequenceMaxValue + ) + if (currentDialectTest.supportsCreateSequence) { val allSequences = currentDialectTest.sequences().map { name -> Sequence(name) }.toSet() allSequences.forEach { sequence -> @@ -769,33 +778,34 @@ class DatabaseMigrationTests : DatabaseTestsBase() { private fun expectedCreateSequenceStatement(sequenceName: String) = "CREATE SEQUENCE${" IF NOT EXISTS".takeIf { currentDialectTest.supportsIfNotExists } ?: ""} " + - "$sequenceName START WITH 1 MINVALUE 1 MAXVALUE 9223372036854775807" + "$sequenceName START WITH 1 MINVALUE 1 MAXVALUE ${currentDialectTest.sequenceMaxValue}" private fun expectedDropSequenceStatement(sequenceName: String) = "DROP SEQUENCE${" IF EXISTS".takeIf { currentDialectTest.supportsIfNotExists } ?: ""} $sequenceName" - private val sequence = Sequence( - name = "my_sequence", - startWith = 1, - minValue = 1, - maxValue = 9223372036854775807 - ) + private val sequenceName by lazy { "custom_sequence" } - private val sequenceName = "custom_sequence" - - private val tableWithoutAutoIncrement = object : IdTable("test_table") { - override val id: Column> = long("id").entityId() + private val tableWithoutAutoIncrement by lazy { + object : IdTable("test_table") { + override val id: Column> = long("id").entityId() + } } - private val tableWithAutoIncrement = object : IdTable("test_table") { - override val id: Column> = long("id").autoIncrement().entityId() + private val tableWithAutoIncrement by lazy { + object : IdTable("test_table") { + override val id: Column> = long("id").autoIncrement().entityId() + } } - private val tableWithAutoIncrementCustomSequence = object : IdTable("test_table") { - override val id: Column> = long("id").autoIncrement(sequence).entityId() + private val tableWithAutoIncrementCustomSequence by lazy { + object : IdTable("test_table") { + override val id: Column> = long("id").autoIncrement(sequence).entityId() + } } - private val tableWithAutoIncrementSequenceName = object : IdTable("test_table") { - override val id: Column> = long("id").autoIncrement(sequenceName).entityId() + private val tableWithAutoIncrementSequenceName by lazy { + object : IdTable("test_table") { + override val id: Column> = long("id").autoIncrement(sequenceName).entityId() + } } }