Skip to content

Commit

Permalink
fix: Add support for creating sequence in MariaDB (#2324)
Browse files Browse the repository at this point in the history
* fix: Add support for creating sequence in MariaDB

* test: EXPOSED-662 add new create table test

* fix: add mariadb cases to DatabaseMigrationTests

* Revert "test: EXPOSED-662 add new create table test"

This reverts commit e6bb1df.

* fix: add mariadb one more case to DatabaseMigrationTests

* fix: table's name must not be more than 64 characters in MariaDB

* fix: supportsSequenceAsGeneratedKeys is false

* fix: sequences table implemented in 11.5 version

* fix: api update

* fix: change version from 11.5 to 10.3

* fix: api fix

* Revert "fix: table's name must not be more than 64 characters in MariaDB"

This reverts commit cf1c97e.

* fix: make constant private
  • Loading branch information
devgor88 authored Jan 27, 2025
1 parent a587ad9 commit e815785
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 1 deletion.
7 changes: 7 additions & 0 deletions exposed-core/api/exposed-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -662,13 +662,16 @@ public final class org/jetbrains/exposed/sql/Database {
public final fun getDefaultFetchSize ()Ljava/lang/Integer;
public final fun getDialect ()Lorg/jetbrains/exposed/sql/vendors/DatabaseDialect;
public final fun getIdentifierManager ()Lorg/jetbrains/exposed/sql/statements/api/IdentifierManagerApi;
public final fun getMajorVersion ()I
public final fun getMinorVersion ()I
public final fun getSupportsAlterTableWithAddColumn ()Z
public final fun getSupportsAlterTableWithDropColumn ()Z
public final fun getSupportsMultipleResultSets ()Z
public final fun getUrl ()Ljava/lang/String;
public final fun getUseNestedTransactions ()Z
public final fun getVendor ()Ljava/lang/String;
public final fun getVersion ()Ljava/math/BigDecimal;
public final fun isVersionCovers (II)Z
public final fun isVersionCovers (Ljava/math/BigDecimal;)Z
public final fun setUseNestedTransactions (Z)V
public fun toString ()Ljava/lang/String;
Expand Down Expand Up @@ -3571,6 +3574,8 @@ public abstract class org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMe
public abstract fun getDatabaseProductVersion ()Ljava/lang/String;
public abstract fun getDefaultIsolationLevel ()I
public abstract fun getIdentifierManager ()Lorg/jetbrains/exposed/sql/statements/api/IdentifierManagerApi;
public abstract fun getMajorVersion ()I
public abstract fun getMinorVersion ()I
public abstract fun getSchemaNames ()Ljava/util/List;
public abstract fun getSupportsAlterTableWithAddColumn ()Z
public abstract fun getSupportsAlterTableWithDropColumn ()Z
Expand Down Expand Up @@ -4158,7 +4163,9 @@ 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 getSupportsCreateSequence ()Z
public fun getSupportsOnlyIdentifiersInGeneratedKeys ()Z
public fun getSupportsSequenceAsGeneratedKeys ()Z
public fun getSupportsSetDefaultReferenceOption ()Z
}

Expand Down
10 changes: 10 additions & 0 deletions exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ class Database private constructor(
/** Whether the version number of the database is equal to or greater than the provided [version]. */
fun isVersionCovers(version: BigDecimal) = this.version >= version

/** The major version number of the database as a [Int]. */
val majorVersion by lazy { metadata { majorVersion } }

/** The minor version number of the database as a [Int]. */
val minorVersion by lazy { metadata { minorVersion } }

/** Whether the version number of the database is equal to or greater than the provided [majorVersion] and [minorVersion]. */
fun isVersionCovers(majorVersion: Int, minorVersion: Int) =
this.majorVersion >= majorVersion && this.minorVersion >= minorVersion

/** Whether the database supports ALTER TABLE with an add column clause. */
val supportsAlterTableWithAddColumn by lazy(
LazyThreadSafetyMode.NONE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ abstract class ExposedDatabaseMetadata(val database: String) {
/** The version number of the database as a `BigDecimal`. */
abstract val version: BigDecimal

/** The major version number of the database. */
abstract val majorVersion: Int

/** The minor version number of the database. */
abstract val minorVersion: Int

/** The name of the database based on the name of the underlying JDBC driver. */
abstract val databaseDialectName: String

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.jetbrains.exposed.sql.vendors

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.TransactionManager

internal object MariaDBFunctionProvider : MysqlFunctionProvider() {
override fun nextVal(seq: Sequence, builder: QueryBuilder) = builder {
Expand Down Expand Up @@ -70,6 +71,12 @@ class MariaDBDialect : MysqlDialect() {
override val functionProvider: FunctionProvider = MariaDBFunctionProvider
override val supportsOnlyIdentifiersInGeneratedKeys: Boolean = true
override val supportsSetDefaultReferenceOption: Boolean = false
override val supportsCreateSequence: Boolean by lazy {
TransactionManager.current().db.isVersionCovers(SEQUENCE_MIN_MAJOR_VERSION, SEQUENCE_MIN_MINOR_VERSION)
}

// actually MariaDb supports it but jdbc driver prepares statement without RETURNING clause
override val supportsSequenceAsGeneratedKeys: Boolean = false

override fun createIndex(index: Index): String {
if (index.functions != null) {
Expand All @@ -81,5 +88,8 @@ class MariaDBDialect : MysqlDialect() {
return super.createIndex(index)
}

companion object : DialectNameProvider("MariaDB")
companion object : DialectNameProvider("MariaDB") {
private const val SEQUENCE_MIN_MAJOR_VERSION = 10
private const val SEQUENCE_MIN_MINOR_VERSION = 3
}
}
2 changes: 2 additions & 0 deletions exposed-jdbc/api/exposed-jdbc.api
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadat
public fun getDatabaseProductVersion ()Ljava/lang/String;
public fun getDefaultIsolationLevel ()I
public fun getIdentifierManager ()Lorg/jetbrains/exposed/sql/statements/api/IdentifierManagerApi;
public fun getMajorVersion ()I
public final fun getMetadata ()Ljava/sql/DatabaseMetaData;
public fun getMinorVersion ()I
public fun getSchemaNames ()Ljava/util/List;
public fun getSupportsAlterTableWithAddColumn ()Z
public fun getSupportsAlterTableWithDropColumn ()Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import java.util.concurrent.ConcurrentHashMap
class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) : ExposedDatabaseMetadata(database) {
override val url: String by lazyMetadata { url }
override val version: BigDecimal by lazyMetadata { BigDecimal("$databaseMajorVersion.$databaseMinorVersion") }
override val majorVersion: Int by lazyMetadata { databaseMajorVersion }
override val minorVersion: Int by lazyMetadata { databaseMinorVersion }

override val databaseDialectName: String by lazyMetadata {
when (driverName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class TransactionExecTests : DatabaseTestsBase() {
TestDB.SQLSERVER -> "SELECT current_value AS $columnAlias FROM sys.sequences"
TestDB.ORACLE -> "SELECT ${ExecTable.id.autoIncColumnType?.autoincSeq}.CURRVAL AS $columnAlias FROM DUAL"
TestDB.POSTGRESQL -> "SELECT lastval() AS $columnAlias"
TestDB.MARIADB -> "SELECT LASTVAL(${ExecTable.id.autoIncColumnType?.autoincSeq}) AS $columnAlias"
else -> "SELECT LAST_INSERT_ID() AS $columnAlias"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,16 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
withDb(excludeSettings = listOf(TestDB.SQLITE)) { testDb ->
if (currentDialectTest.supportsCreateSequence) {
try {
// MariaDB does not allow to create auto column without defining it as a key
val tableWithAutoIncrement = if (testDb == TestDB.MARIADB) {
object : IdTable<Long>("test_table") {
override val id: Column<EntityID<Long>> = long("id").autoIncrement().entityId()
override val primaryKey = PrimaryKey(id)
}
} else {
tableWithAutoIncrement
}

SchemaUtils.create(tableWithAutoIncrement)

assertEquals(0, MigrationUtils.statementsRequiredForDatabaseMigration(tableWithAutoIncrement, withLogs = false).size)
Expand Down Expand Up @@ -526,6 +536,11 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
assertEquals(1, statements.size)
assertEquals("ALTER TABLE TEST_TABLE ALTER COLUMN ID BIGINT AUTO_INCREMENT NOT NULL", statements[0])
}
TestDB.MARIADB -> {
assertEquals(2, statements.size)
assertEquals("ALTER TABLE test_table MODIFY COLUMN id BIGINT AUTO_INCREMENT NOT NULL", statements[0])
assertEquals(expectedDropSequenceStatement(sequenceName), statements[1])
}
else -> {
assertEquals(2, statements.size)
assertTrue(statements[0].startsWith("ALTER TABLE TEST_TABLE ALTER COLUMN ID", ignoreCase = true))
Expand Down Expand Up @@ -633,6 +648,11 @@ class DatabaseMigrationTests : DatabaseTestsBase() {
assertEquals(1, statements.size)
assertEquals("ALTER TABLE TEST_TABLE ALTER COLUMN ID BIGINT AUTO_INCREMENT NOT NULL", statements[0])
}
TestDB.MARIADB -> {
assertEquals(2, statements.size)
assertEquals("ALTER TABLE test_table MODIFY COLUMN id BIGINT AUTO_INCREMENT NOT NULL", statements[0])
assertEquals(expectedDropSequenceStatement(sequence.name), statements[1])
}
else -> {
assertEquals(2, statements.size)
assertTrue(statements[0].startsWith("ALTER TABLE TEST_TABLE ALTER COLUMN ID", ignoreCase = true))
Expand Down

0 comments on commit e815785

Please sign in to comment.