From ba7dbfce2a48382c576b8696bce83f2c87a7cd74 Mon Sep 17 00:00:00 2001 From: Chantal Loncle <82039410+bog-walk@users.noreply.github.com> Date: Fri, 29 Sep 2023 13:39:28 -0400 Subject: [PATCH 1/3] deprecate: Raise deprecation level of currentScheme property Raise deprecation level of ExposedDatabaseMetadata.currentScheme from ERROR to WARNING. This property was meant to be private/protected within classes that implement the interface, but has been used in VendorDialect` and 1 unit test. A new abstract fun tableNamesByCurrentSchema() is introduced to abstract away the schema from the core module. Ideally this function would return a List but tableExists() needs to know about the current scheme name, so it instead returns a Pair to provide that. --- exposed-core/api/exposed-core.api | 4 +- .../statements/api/ExposedDatabaseMetadata.kt | 4 +- .../exposed/sql/vendors/MysqlDialect.kt | 21 ++++------ .../exposed/sql/vendors/VendorDialect.kt | 39 ++++++++++++------- exposed-jdbc/api/exposed-jdbc.api | 1 + .../jdbc/JdbcDatabaseMetadataImpl.kt | 24 +++++++++--- .../exposed/sql/tests/shared/SchemaTests.kt | 6 +-- 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 8a1dd9a39e..05f390cf19 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -2998,6 +2998,7 @@ public abstract class org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMe public abstract fun getVersion ()Ljava/math/BigDecimal; public abstract fun resetCurrentScheme ()V public abstract fun tableConstraints (Ljava/util/List;)Ljava/util/Map; + public abstract fun tableNamesByCurrentSchema (Ljava/util/Map;)Lkotlin/Pair; } public abstract class org/jetbrains/exposed/sql/statements/api/ExposedSavepoint { @@ -3532,8 +3533,8 @@ public class org/jetbrains/exposed/sql/vendors/MysqlDialect : org/jetbrains/expo public fun isAllowedAsColumnDefault (Lorg/jetbrains/exposed/sql/Expression;)Z public final fun isFractionDateTimeSupported ()Z public final fun isTimeZoneOffsetSupported ()Z + protected fun metadataMatchesTable (Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Table;)Z public fun setSchema (Lorg/jetbrains/exposed/sql/Schema;)Ljava/lang/String; - public fun tableExists (Lorg/jetbrains/exposed/sql/Table;)Z } public final class org/jetbrains/exposed/sql/vendors/MysqlDialect$Companion : org/jetbrains/exposed/sql/vendors/VendorDialect$DialectNameProvider { @@ -3704,6 +3705,7 @@ public abstract class org/jetbrains/exposed/sql/vendors/VendorDialect : org/jetb public fun getSupportsWindowFrameGroupsMode ()Z public fun isAllowedAsColumnDefault (Lorg/jetbrains/exposed/sql/Expression;)Z public fun listDatabases ()Ljava/lang/String; + protected fun metadataMatchesTable (Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/exposed/sql/Table;)Z public fun modifyColumn (Lorg/jetbrains/exposed/sql/Column;Lorg/jetbrains/exposed/sql/ColumnDiff;)Ljava/util/List; protected final fun quoteIdentifierWhenWrongCaseOrNecessary (Ljava/lang/String;Lorg/jetbrains/exposed/sql/Transaction;)Ljava/lang/String; public fun resetCaches ()V 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 19e6225062..1093be046c 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 @@ -23,13 +23,15 @@ abstract class ExposedDatabaseMetadata(val database: String) { @Deprecated( message = "it's temporary solution which will be replaced in a future releases. Do not use it in your code", - level = DeprecationLevel.WARNING + level = DeprecationLevel.ERROR ) abstract val currentScheme: String abstract fun resetCurrentScheme() abstract val tableNames: Map> abstract val schemaNames: List + abstract fun tableNamesByCurrentSchema(tableNamesCache: Map>?): Pair> + abstract fun columns(vararg tables: Table): Map> abstract fun existingIndices(vararg tables: Table): Map> diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt index c1d1b13c89..3604a936d5 100644 --- a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/MysqlDialect.kt @@ -384,20 +384,13 @@ open class MysqlDialect : VendorDialect(dialectName, MysqlDataTypeProvider, Mysq override fun dropSchema(schema: Schema, cascade: Boolean): String = "DROP SCHEMA IF EXISTS ${schema.identifier}" - override fun tableExists(table: Table): Boolean { - val tableScheme = table.schemaName - val scheme = tableScheme?.inProperCase() ?: TransactionManager.current().connection.metadata { currentScheme } - val allTables = getAllTableNamesCache().getValue(scheme) - - return allTables.any { - when { - tableScheme != null -> it == table.nameInDatabaseCase() - scheme.isEmpty() -> it == table.nameInDatabaseCaseUnquoted() - else -> { - val sanitizedTableName = table.tableNameWithoutScheme - val nameInDb = "$scheme.$sanitizedTableName".inProperCase() - it == nameInDb - } + override fun String.metadataMatchesTable(schema: String, table: Table): Boolean { + return when { + schema.isEmpty() -> this == table.nameInDatabaseCaseUnquoted() + else -> { + val sanitizedTableName = table.tableNameWithoutScheme + val nameInDb = "$schema.$sanitizedTableName".inProperCase() + this == nameInDb } } } 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 b9dc21d89e..1fdcd572b5 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 @@ -28,7 +28,7 @@ abstract class VendorDialect( val allTablesNames: List get() { val connection = TransactionManager.current().connection - return getAllTableNamesCache().getValue(connection.metadata { currentScheme }) + return connection.metadata { tableNamesByCurrentSchema(getAllTableNamesCache()) }.second } protected fun getAllTableNamesCache(): Map> { @@ -57,22 +57,31 @@ abstract class VendorDialect( * Using `allTablesNames` field is the preferred way. */ override fun allTablesNames(): List = TransactionManager.current().connection.metadata { - tableNames.getValue(currentScheme) - } + tableNamesByCurrentSchema(null) + }.second override fun tableExists(table: Table): Boolean { - val tableScheme = table.schemaName - val scheme = tableScheme?.inProperCase() ?: TransactionManager.current().connection.metadata { currentScheme } - val allTables = getAllTableNamesCache().getValue(scheme) - return allTables.any { - when { - tableScheme != null -> it == table.nameInDatabaseCase() - scheme.isEmpty() -> it == table.nameInDatabaseCaseUnquoted() - else -> { - val sanitizedTableName = table.tableNameWithoutSchemeSanitized - val nameInDb = "$scheme.$sanitizedTableName".inProperCase() - it == nameInDb - } + return table.schemaName?.let { schema -> + getAllTableNamesCache().getValue(schema.inProperCase()).any { + it == table.nameInDatabaseCase() + } + } ?: run { + val (schema, allTables) = TransactionManager.current().connection.metadata { + tableNamesByCurrentSchema(getAllTableNamesCache()) + } + allTables.any { + it.metadataMatchesTable(schema, table) + } + } + } + + protected open fun String.metadataMatchesTable(schema: String, table: Table): Boolean { + return when { + schema.isEmpty() -> this == table.nameInDatabaseCaseUnquoted() + else -> { + val sanitizedTableName = table.tableNameWithoutSchemeSanitized + val nameInDb = "$schema.$sanitizedTableName".inProperCase() + this == nameInDb } } } diff --git a/exposed-jdbc/api/exposed-jdbc.api b/exposed-jdbc/api/exposed-jdbc.api index d2401db896..edac2b6b7f 100644 --- a/exposed-jdbc/api/exposed-jdbc.api +++ b/exposed-jdbc/api/exposed-jdbc.api @@ -53,6 +53,7 @@ public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadat public fun getVersion ()Ljava/math/BigDecimal; public fun resetCurrentScheme ()V public fun tableConstraints (Ljava/util/List;)Ljava/util/Map; + public fun tableNamesByCurrentSchema (Ljava/util/Map;)Lkotlin/Pair; } public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl$Companion { 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 fc94340607..55c1c65d7b 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 @@ -38,7 +38,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) private val databaseName get() = when (databaseDialectName) { - MysqlDialect.dialectName, MariaDBDialect.dialectName -> currentScheme + MysqlDialect.dialectName, MariaDBDialect.dialectName -> _currentScheme!! else -> database } @@ -72,6 +72,10 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) return field!! } + @Deprecated( + message = "This will be removed when the interface property is fully deprecated", + level = DeprecationLevel.ERROR + ) override val currentScheme: String get() = _currentScheme!! override fun resetCurrentScheme() { @@ -125,6 +129,14 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) return schemas.map { identifierManager.inProperCase(it) } } + /** + * Returns the default schema name and a list of its existing table names, as a pair, + * found either by reading metadata or from a cache of previously read metadata. + */ + override fun tableNamesByCurrentSchema(tableNamesCache: Map>?): Pair> { + return _currentScheme!! to (tableNamesCache ?: tableNames).getValue(_currentScheme!!) + } + private fun ResultSet.extractColumns(): List { val result = mutableListOf() while (next()) { @@ -136,11 +148,11 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) override fun columns(vararg tables: Table): Map> { val result = mutableMapOf>() val useSchemaInsteadOfDatabase = currentDialect is MysqlDialect - val tablesBySchema = tables.groupBy { identifierManager.inProperCase(it.schemaName ?: currentScheme) } + val tablesBySchema = tables.groupBy { identifierManager.inProperCase(it.schemaName ?: _currentScheme!!) } for ((schema, schemaTables) in tablesBySchema.entries) { for (table in schemaTables) { - val catalog = if (!useSchemaInsteadOfDatabase || schema == currentScheme) databaseName else schema + val catalog = if (!useSchemaInsteadOfDatabase || schema == _currentScheme!!) databaseName else schema val rs = metadata.getColumns(catalog, schema, table.nameInDatabaseCaseUnquoted(), "%") val columns = rs.extractColumns() check(columns.isNotEmpty()) @@ -208,7 +220,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) rs.close() names } - val storedIndexTable = if (tableSchema == currentScheme) table.nameInDatabaseCase() else table.nameInDatabaseCaseUnquoted() + val storedIndexTable = if (tableSchema == _currentScheme!!) table.nameInDatabaseCase() else table.nameInDatabaseCaseUnquoted() val rs = metadata.getIndexInfo(catalog, tableSchema, storedIndexTable, false, false) val tmpIndices = hashMapOf, MutableList>() @@ -312,8 +324,8 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) * metadata if 'my_schema' is used as the database name. */ private fun tableCatalogAndSchema(table: Table): Pair { - val tableSchema = identifierManager.inProperCase(table.schemaName ?: currentScheme) - return if (currentDialect is MysqlDialect && tableSchema != currentScheme) { + val tableSchema = identifierManager.inProperCase(table.schemaName ?: _currentScheme!!) + return if (currentDialect is MysqlDialect && tableSchema != _currentScheme!!) { tableSchema to tableSchema } else { databaseName to tableSchema diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt index ff7e68fe2b..6f2b7683e0 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt @@ -140,7 +140,7 @@ class SchemaTests : DatabaseTestsBase() { transaction { connection.metadata { - assertEquals("PUBLIC", currentScheme) + assertEquals("PUBLIC", tableNamesByCurrentSchema(null).first) } } @@ -154,13 +154,13 @@ class SchemaTests : DatabaseTestsBase() { transaction(db) { connection.metadata { - val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(currentScheme) + val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(tableNamesByCurrentSchema(null).first) assertEquals(schema.identifier, currentScheme) } // Nested transaction transaction(db) { connection.metadata { - val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(currentScheme) + val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(tableNamesByCurrentSchema(null).first) assertEquals(schema.identifier, currentScheme) } } From b86de329f1fe9dc6f0dba731a0936534a5a244b3 Mon Sep 17 00:00:00 2001 From: Chantal Loncle <82039410+bog-walk@users.noreply.github.com> Date: Wed, 4 Oct 2023 21:05:25 -0400 Subject: [PATCH 2/3] deprecate: Raise deprecation level of currentScheme property Change name of private property to no longer have underscore prefix. --- .../jdbc/JdbcDatabaseMetadataImpl.kt | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) 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 55c1c65d7b..fdc76a0530 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 @@ -38,7 +38,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) private val databaseName get() = when (databaseDialectName) { - MysqlDialect.dialectName, MariaDBDialect.dialectName -> _currentScheme!! + MysqlDialect.dialectName, MariaDBDialect.dialectName -> currentSchema!! else -> database } @@ -56,7 +56,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) } } - private var _currentScheme: String? = null + private var currentSchema: String? = null get() { if (field == null) { field = try { @@ -76,10 +76,10 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) message = "This will be removed when the interface property is fully deprecated", level = DeprecationLevel.ERROR ) - override val currentScheme: String get() = _currentScheme!! + override val currentScheme: String get() = currentSchema!! override fun resetCurrentScheme() { - _currentScheme = null + currentSchema = null } private inner class CachableMapWithDefault( @@ -134,7 +134,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) * found either by reading metadata or from a cache of previously read metadata. */ override fun tableNamesByCurrentSchema(tableNamesCache: Map>?): Pair> { - return _currentScheme!! to (tableNamesCache ?: tableNames).getValue(_currentScheme!!) + return currentSchema!! to (tableNamesCache ?: tableNames).getValue(currentSchema!!) } private fun ResultSet.extractColumns(): List { @@ -148,11 +148,11 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) override fun columns(vararg tables: Table): Map> { val result = mutableMapOf>() val useSchemaInsteadOfDatabase = currentDialect is MysqlDialect - val tablesBySchema = tables.groupBy { identifierManager.inProperCase(it.schemaName ?: _currentScheme!!) } + val tablesBySchema = tables.groupBy { identifierManager.inProperCase(it.schemaName ?: currentSchema!!) } for ((schema, schemaTables) in tablesBySchema.entries) { for (table in schemaTables) { - val catalog = if (!useSchemaInsteadOfDatabase || schema == _currentScheme!!) databaseName else schema + val catalog = if (!useSchemaInsteadOfDatabase || schema == currentSchema!!) databaseName else schema val rs = metadata.getColumns(catalog, schema, table.nameInDatabaseCaseUnquoted(), "%") val columns = rs.extractColumns() check(columns.isNotEmpty()) @@ -220,7 +220,7 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) rs.close() names } - val storedIndexTable = if (tableSchema == _currentScheme!!) table.nameInDatabaseCase() else table.nameInDatabaseCaseUnquoted() + val storedIndexTable = if (tableSchema == currentSchema!!) table.nameInDatabaseCase() else table.nameInDatabaseCaseUnquoted() val rs = metadata.getIndexInfo(catalog, tableSchema, storedIndexTable, false, false) val tmpIndices = hashMapOf, MutableList>() @@ -324,8 +324,8 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) * metadata if 'my_schema' is used as the database name. */ private fun tableCatalogAndSchema(table: Table): Pair { - val tableSchema = identifierManager.inProperCase(table.schemaName ?: _currentScheme!!) - return if (currentDialect is MysqlDialect && tableSchema != _currentScheme!!) { + val tableSchema = identifierManager.inProperCase(table.schemaName ?: currentSchema!!) + return if (currentDialect is MysqlDialect && tableSchema != currentSchema!!) { tableSchema to tableSchema } else { databaseName to tableSchema From 0769791aafebb109c414062bbb9c1abc98bcc9b5 Mon Sep 17 00:00:00 2001 From: Chantal Loncle <82039410+bog-walk@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:48:03 -0400 Subject: [PATCH 3/3] deprecate: Raise deprecation level of currentScheme property Add data class SchemaMetadata as nre return type of tableNamesBySchema(). --- exposed-core/api/exposed-core.api | 15 ++++++++++++++- .../sql/statements/api/ExposedDatabaseMetadata.kt | 3 ++- .../exposed/sql/vendors/SchemaMetadata.kt | 11 +++++++++++ .../exposed/sql/vendors/VendorDialect.kt | 6 +++--- exposed-jdbc/api/exposed-jdbc.api | 2 +- .../statements/jdbc/JdbcDatabaseMetadataImpl.kt | 7 ++++--- .../exposed/sql/tests/shared/SchemaTests.kt | 10 +++++++--- 7 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SchemaMetadata.kt diff --git a/exposed-core/api/exposed-core.api b/exposed-core/api/exposed-core.api index 05f390cf19..754d3e003a 100644 --- a/exposed-core/api/exposed-core.api +++ b/exposed-core/api/exposed-core.api @@ -2998,7 +2998,7 @@ public abstract class org/jetbrains/exposed/sql/statements/api/ExposedDatabaseMe public abstract fun getVersion ()Ljava/math/BigDecimal; public abstract fun resetCurrentScheme ()V public abstract fun tableConstraints (Ljava/util/List;)Ljava/util/Map; - public abstract fun tableNamesByCurrentSchema (Ljava/util/Map;)Lkotlin/Pair; + public abstract fun tableNamesByCurrentSchema (Ljava/util/Map;)Lorg/jetbrains/exposed/sql/vendors/SchemaMetadata; } public abstract class org/jetbrains/exposed/sql/statements/api/ExposedSavepoint { @@ -3658,6 +3658,19 @@ public final class org/jetbrains/exposed/sql/vendors/SQLiteDialect$Companion : o public final fun getENABLE_UPDATE_DELETE_LIMIT ()Z } +public final class org/jetbrains/exposed/sql/vendors/SchemaMetadata { + public fun (Ljava/lang/String;Ljava/util/List;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/List; + public final fun copy (Ljava/lang/String;Ljava/util/List;)Lorg/jetbrains/exposed/sql/vendors/SchemaMetadata; + public static synthetic fun copy$default (Lorg/jetbrains/exposed/sql/vendors/SchemaMetadata;Ljava/lang/String;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/exposed/sql/vendors/SchemaMetadata; + public fun equals (Ljava/lang/Object;)Z + public final fun getSchemaName ()Ljava/lang/String; + public final fun getTableNames ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + public abstract class org/jetbrains/exposed/sql/vendors/VendorDialect : org/jetbrains/exposed/sql/vendors/DatabaseDialect { public fun (Ljava/lang/String;Lorg/jetbrains/exposed/sql/vendors/DataTypeProvider;Lorg/jetbrains/exposed/sql/vendors/FunctionProvider;)V public fun addPrimaryKey (Lorg/jetbrains/exposed/sql/Table;Ljava/lang/String;[Lorg/jetbrains/exposed/sql/Column;)Ljava/lang/String; 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 1093be046c..aaa0b4c26f 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 @@ -5,6 +5,7 @@ import org.jetbrains.exposed.sql.Index import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.vendors.ColumnMetadata import org.jetbrains.exposed.sql.vendors.PrimaryKeyMetadata +import org.jetbrains.exposed.sql.vendors.SchemaMetadata import java.math.BigDecimal abstract class ExposedDatabaseMetadata(val database: String) { @@ -30,7 +31,7 @@ abstract class ExposedDatabaseMetadata(val database: String) { abstract val tableNames: Map> abstract val schemaNames: List - abstract fun tableNamesByCurrentSchema(tableNamesCache: Map>?): Pair> + abstract fun tableNamesByCurrentSchema(tableNamesCache: Map>?): SchemaMetadata abstract fun columns(vararg tables: Table): Map> diff --git a/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SchemaMetadata.kt b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SchemaMetadata.kt new file mode 100644 index 0000000000..4e9a59aea5 --- /dev/null +++ b/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/vendors/SchemaMetadata.kt @@ -0,0 +1,11 @@ +package org.jetbrains.exposed.sql.vendors + +/** + * Represents metadata information about the current schema and its associated tables. + */ +data class SchemaMetadata( + /** Name of the current schema. */ + val schemaName: String, + /** Names of the existing tables in the current schema. */ + val tableNames: List +) 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 1fdcd572b5..cea7605f60 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 @@ -28,7 +28,7 @@ abstract class VendorDialect( val allTablesNames: List get() { val connection = TransactionManager.current().connection - return connection.metadata { tableNamesByCurrentSchema(getAllTableNamesCache()) }.second + return connection.metadata { tableNamesByCurrentSchema(getAllTableNamesCache()).tableNames } } protected fun getAllTableNamesCache(): Map> { @@ -57,8 +57,8 @@ abstract class VendorDialect( * Using `allTablesNames` field is the preferred way. */ override fun allTablesNames(): List = TransactionManager.current().connection.metadata { - tableNamesByCurrentSchema(null) - }.second + tableNamesByCurrentSchema(null).tableNames + } override fun tableExists(table: Table): Boolean { return table.schemaName?.let { schema -> diff --git a/exposed-jdbc/api/exposed-jdbc.api b/exposed-jdbc/api/exposed-jdbc.api index edac2b6b7f..66efb4a935 100644 --- a/exposed-jdbc/api/exposed-jdbc.api +++ b/exposed-jdbc/api/exposed-jdbc.api @@ -53,7 +53,7 @@ public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadat public fun getVersion ()Ljava/math/BigDecimal; public fun resetCurrentScheme ()V public fun tableConstraints (Ljava/util/List;)Ljava/util/Map; - public fun tableNamesByCurrentSchema (Ljava/util/Map;)Lkotlin/Pair; + public fun tableNamesByCurrentSchema (Ljava/util/Map;)Lorg/jetbrains/exposed/sql/vendors/SchemaMetadata; } public final class org/jetbrains/exposed/sql/statements/jdbc/JdbcDatabaseMetadataImpl$Companion { 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 fdc76a0530..6880fb1ff6 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 @@ -130,11 +130,12 @@ class JdbcDatabaseMetadataImpl(database: String, val metadata: DatabaseMetaData) } /** - * Returns the default schema name and a list of its existing table names, as a pair, + * Returns the default schema name and a list of its existing table names, as [SchemaMetadata], * found either by reading metadata or from a cache of previously read metadata. */ - override fun tableNamesByCurrentSchema(tableNamesCache: Map>?): Pair> { - return currentSchema!! to (tableNamesCache ?: tableNames).getValue(currentSchema!!) + override fun tableNamesByCurrentSchema(tableNamesCache: Map>?): SchemaMetadata { + val tablesInSchema = (tableNamesCache ?: tableNames).getValue(currentSchema!!) + return SchemaMetadata(currentSchema!!, tablesInSchema) } private fun ResultSet.extractColumns(): List { diff --git a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt index 6f2b7683e0..9748ea54e6 100644 --- a/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt +++ b/exposed-tests/src/test/kotlin/org/jetbrains/exposed/sql/tests/shared/SchemaTests.kt @@ -140,7 +140,7 @@ class SchemaTests : DatabaseTestsBase() { transaction { connection.metadata { - assertEquals("PUBLIC", tableNamesByCurrentSchema(null).first) + assertEquals("PUBLIC", tableNamesByCurrentSchema(null).schemaName) } } @@ -154,13 +154,17 @@ class SchemaTests : DatabaseTestsBase() { transaction(db) { connection.metadata { - val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(tableNamesByCurrentSchema(null).first) + val currentScheme = db.identifierManager.cutIfNecessaryAndQuote( + tableNamesByCurrentSchema(null).schemaName + ) assertEquals(schema.identifier, currentScheme) } // Nested transaction transaction(db) { connection.metadata { - val currentScheme = db.identifierManager.cutIfNecessaryAndQuote(tableNamesByCurrentSchema(null).first) + val currentScheme = db.identifierManager.cutIfNecessaryAndQuote( + tableNamesByCurrentSchema(null).schemaName + ) assertEquals(schema.identifier, currentScheme) } }