diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 73f1dd8a57..cdef6c01e9 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -1992,6 +1992,7 @@ public final class org/jetbrains/exposed/sql/Sequence { public synthetic fun (Ljava/lang/String;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/lang/Long;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun createStatement ()Ljava/util/List; public final fun dropStatement ()Ljava/util/List; + public final fun exists ()Z public final fun getCache ()Ljava/lang/Long; public final fun getCycle ()Ljava/lang/Boolean; public final fun getDdl ()Ljava/util/List; @@ -3161,6 +3162,7 @@ public abstract class org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMe public abstract fun columns ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public abstract fun existingIndices ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public abstract fun existingPrimaryKeys ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; + public abstract fun existingSequences ()Ljava/util/List; public abstract synthetic fun getCurrentScheme ()Ljava/lang/String; public final fun getDatabase ()Ljava/lang/String; public abstract fun getDatabaseDialectName ()Ljava/lang/String; @@ -3430,6 +3432,7 @@ public abstract interface class org/jetbrains/exposed/sql/vendors/DatabaseDialec public abstract fun dropSchema (Lorg/jetbrains/exposed/sql/Schema;Z)Ljava/lang/String; public abstract fun existingIndices ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public abstract fun existingPrimaryKeys ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; + public abstract fun existingSequences ()Ljava/util/List; public abstract fun getDataTypeProvider ()Lorg/jetbrains/exposed/sql/vendors/DataTypeProvider; public abstract fun getDatabase ()Ljava/lang/String; public abstract fun getDefaultReferenceOption ()Lorg/jetbrains/exposed/sql/ReferenceOption; @@ -3460,6 +3463,7 @@ public abstract interface class org/jetbrains/exposed/sql/vendors/DatabaseDialec public abstract fun resetSchemaCaches ()V public abstract fun resolveRefOptionFromJdbc (I)Lorg/jetbrains/exposed/sql/ReferenceOption; public abstract fun schemaExists (Lorg/jetbrains/exposed/sql/Schema;)Z + public abstract fun sequenceExists (Lorg/jetbrains/exposed/sql/Sequence;)Z public abstract fun setSchema (Lorg/jetbrains/exposed/sql/Schema;)Ljava/lang/String; public abstract fun supportsSelectForUpdate ()Z public abstract fun tableColumns ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; @@ -3892,6 +3896,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/VendorDialect : org/jetb public fun dropSchema (Lorg/jetbrains/exposed/sql/Schema;Z)Ljava/lang/String; public fun existingIndices ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public fun existingPrimaryKeys ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; + public fun existingSequences ()Ljava/util/List; protected fun fillConstraintCacheForTables (Ljava/util/List;)V public final fun filterCondition (Lorg/jetbrains/exposed/sql/Index;)Ljava/lang/String; protected final fun getAllTableNamesCache ()Ljava/util/Map; @@ -3930,6 +3935,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/VendorDialect : org/jetb public fun resetSchemaCaches ()V public fun resolveRefOptionFromJdbc (I)Lorg/jetbrains/exposed/sql/ReferenceOption; public fun schemaExists (Lorg/jetbrains/exposed/sql/Schema;)Z + public fun sequenceExists (Lorg/jetbrains/exposed/sql/Sequence;)Z public fun setSchema (Lorg/jetbrains/exposed/sql/Schema;)Ljava/lang/String; public fun supportsSelectForUpdate ()Z public fun tableColumns ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Sequence.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Sequence.kt index 7ca4f8ebf6..2084eab86c 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Sequence.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Sequence.kt @@ -76,4 +76,6 @@ class Sequence( return listOf(dropSequenceDDL) } + + fun exists(): Boolean = currentDialect.sequenceExists(this) } diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt index 78c2e1db0e..2730d2f352 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMetadata.kt @@ -67,6 +67,8 @@ abstract class ExposedDatabaseMetadata(val database: String) { /** Returns a map with the [PrimaryKeyMetadata] in each of the specified [tables]. */ abstract fun existingPrimaryKeys(vararg tables: Table): Map + abstract fun existingSequences(): List + /** * Returns a map with the [ForeignKeyConstraint] of all the defined columns in each of the specified [tables], * with the table name used as the key. 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 4fbc861733..1f1d20e368 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 @@ -87,6 +87,8 @@ interface DatabaseDialect { /** Checks if the specified schema exists. */ fun schemaExists(schema: Schema): Boolean + fun sequenceExists(sequence: Sequence): Boolean + fun checkTableMapping(table: Table): Boolean = true /** Returns a map with the column metadata of all the defined columns in each of the specified [tables]. */ @@ -103,6 +105,8 @@ interface DatabaseDialect { /** Returns a map with the primary key metadata in each of the specified [tables]. */ fun existingPrimaryKeys(vararg tables: Table): Map = emptyMap() + fun existingSequences(): List + /** Returns `true` if the dialect supports `SELECT FOR UPDATE` statements, `false` otherwise. */ fun supportsSelectForUpdate(): Boolean diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/VendorDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/VendorDialect.kt index cea7605f60..ae6ccb943d 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/VendorDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/VendorDialect.kt @@ -91,6 +91,11 @@ abstract class VendorDialect( return allSchemas.any { it == schema.identifier.inProperCase() } } + override fun sequenceExists(sequence: Sequence): Boolean { + val allSequences = existingSequences() + return allSequences.any { it == sequence.identifier.inProperCase() } + } + override fun tableColumns(vararg tables: Table): Map> = TransactionManager.current().connection.metadata { columns(*tables) } @@ -116,6 +121,9 @@ abstract class VendorDialect( override fun existingPrimaryKeys(vararg tables: Table): Map = TransactionManager.current().db.metadata { existingPrimaryKeys(*tables) } + override fun existingSequences(): List = + TransactionManager.current().db.metadata { existingSequences() } + private val supportsSelectForUpdate: Boolean by lazy { TransactionManager.current().db.metadata { supportsSelectForUpdate } } diff --git a/exposed-jdbc/api/exposed-jdbc.api b/exposed-jdbc/api/exposed-jdbc.api index 6819de607b..03b013f924 100644 --- a/exposed-jdbc/api/exposed-jdbc.api +++ b/exposed-jdbc/api/exposed-jdbc.api @@ -38,6 +38,7 @@ public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadat public fun columns ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public fun existingIndices ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; public fun existingPrimaryKeys ([Lorg/jetbrains/exposed/sql/Table;)Ljava/util/Map; + public fun existingSequences ()Ljava/util/List; public synthetic fun getCurrentScheme ()Ljava/lang/String; public fun getDatabaseDialectName ()Ljava/lang/String; public fun getDatabaseProductVersion ()Ljava/lang/String; diff --git a/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt b/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt index e983c1ef04..099183925c 100644 --- a/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt +++ b/exposed-jdbc/src/main/kotlin/org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl.kt @@ -285,6 +285,43 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) } } + @Suppress("MagicNumber") + override fun existingSequences(): List { + val sequences = mutableListOf() + + when (currentDialect) { + is OracleDialect -> { + TransactionManager.current().exec("SELECT SEQUENCE_NAME FROM USER_SEQUENCES") { rs -> + while (rs.next()) { + sequences.add(rs.getString("SEQUENCE_NAME")) + } + } + } + is SQLServerDialect -> { + TransactionManager.current().exec("SELECT name FROM sys.sequences") { rs -> + while (rs.next()) { + sequences.add(rs.getString("name")) + } + } + } + is H2Dialect -> { + TransactionManager.current().exec("SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES ") { rs -> + while (rs.next()) { + sequences.add(rs.getString("SEQUENCE_NAME")) + } + } + } + else -> { + val rs = metadata.getTables(null, null, null, arrayOf("SEQUENCE")) + while (rs.next()) { + sequences.add(rs.getString(3)) + } + } + } + + return sequences + } + @Synchronized override fun tableConstraints(tables: List): Map> { val allTables = SchemaUtils.sortTablesByReferences(tables).associateBy { it.nameInDatabaseCaseUnquoted() } 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 322a4d5e50..954f4e5225 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 @@ -7,6 +7,7 @@ import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.tests.DatabaseTestsBase import org.jetbrains.exposed.sql.tests.currentDialectTest import org.jetbrains.exposed.sql.tests.shared.assertEquals +import org.jetbrains.exposed.sql.tests.shared.assertTrue import org.junit.Test import kotlin.test.assertNotNull @@ -132,6 +133,21 @@ class SequencesTests : DatabaseTestsBase() { } } + @Test + fun testSequenceExists() { + withDb { + if (currentDialectTest.supportsCreateSequence) { + try { + SchemaUtils.createSequence(myseq) + + assertTrue(myseq.exists()) + } finally { + SchemaUtils.dropSequence(myseq) + } + } + } + } + private object Developer : Table() { val id = integer("id") var name = varchar("name", 25)