-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: EXPOSED-561 Restructure code in MigrationUtils
and SchemaUtils
to avoid calling currentDialect.tableColumns(*tables)
in MigrationUtils.statementsRequiredForDatabaseMigration
twice
#2279
base: main
Are you sure you want to change the base?
Conversation
8f26c03
to
1d0acf3
Compare
…aUtils` to avoid calling `currentDialect.tableColumns(*tables)` in `MigrationUtils.statementsRequiredForDatabaseMigration` twice `SchemaUtils` and `MigrationUtils` reside in separate modules and need to share non-public functions, so using a common abstract base class with protected functions in the exposed-core module is the most effective and clean solution.
1d0acf3
to
29873e5
Compare
import org.jetbrains.exposed.sql.vendors.H2Dialect | ||
import org.jetbrains.exposed.sql.vendors.MysqlDialect | ||
import org.jetbrains.exposed.sql.vendors.SQLiteDialect | ||
import org.jetbrains.exposed.sql.vendors.currentDialect | ||
import java.io.File | ||
|
||
object MigrationUtils { | ||
/** Utility functions that assist with performing database migrations. */ | ||
object MigrationUtils : BaseSchemaUtils() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that in terms of OOP (at least from my current understanding of MigrationUtils
's purpose) MigrationUtils
should not extend SchemaUtils
(BaseSchemaUtils
) but should use it, because MigrationUtils
is more abstract than SchemaUtils
(SchemaUtils
is responsible for manipulating with single db objects like tables, but MigrationUtils
are supposed to move the whole DB from one state to another).
And as I can see MigrationUtils
overrides nothing from base class.
@@ -102,16 +105,21 @@ object MigrationUtils { | |||
*/ | |||
fun dropUnmappedColumnsStatements(vararg tables: Table, withLogs: Boolean = true): List<String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a problem of that particular PR, but this is a public method, and there is only one test that check that function returns empty list. Probably it would be nice to add one more test, that check for non empty result of that function)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That case is tested, but not by directly calling dropUnmappedColumnsStatements
, in testDropUnmappedColumns
.
@@ -102,16 +105,21 @@ object MigrationUtils { | |||
*/ | |||
fun dropUnmappedColumnsStatements(vararg tables: Table, withLogs: Boolean = true): List<String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And do we have any requests for such functionality? Looks like it's already used in statementsRequiredForDatabaseMigration
that should returns All statements for migration. Probably, the method that checks columns of one (or multiple) tables for deleting could be a part of SchemaUtils
. But it's discussable, just some thoughts on how it could be.
import org.jetbrains.exposed.sql.vendors.H2Dialect | ||
import org.jetbrains.exposed.sql.vendors.MysqlDialect | ||
import org.jetbrains.exposed.sql.vendors.SQLiteDialect | ||
import org.jetbrains.exposed.sql.vendors.currentDialect | ||
import java.io.File | ||
|
||
object MigrationUtils { | ||
/** Utility functions that assist with performing database migrations. */ | ||
object MigrationUtils : BaseSchemaUtils() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also not a problem of that PR, and can't say I finally understand how users will use it, but this class has a method generateMigrationScript
that accepts the list of tables as an argument.
But if you want to create a script, and has hundreds of tables, it could be painful to collect all of them into collection and pass here.
If I use a migration tool, I'd expect that it should search for table objects automatically. As a variant for future improvements we could add one more method that accepts package, and searches for all the table objects (with reflection) within this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is already an improvement that I have on my to-do list.
import java.math.BigDecimal | ||
|
||
/** Base class housing shared code between [SchemaUtils] and [MigrationUtils]. */ | ||
abstract class BaseSchemaUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one another idea of how common part could be extracted.
At the current moment the whole SchemaUtils
looks a bit overloaded. It has methods to generate DDL, and has methods to execute commands to manipulate DB.
We could try to split it into the way to extract DDL generation part into another class, let's call it for now DDLUtils
; and keep inside SchemaUtils
responsibility to execute these DDLs on the database.
In this case we will have common part with DDL statements generation, and two consumers of that class. SchemaUtils
that directly performs it on the DB, and MigrationUtils
that prepare it as a migration scripts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@obabichevjb In that case, how would we make the following function visible only to SchemaUtils
and MigrationUtils
? We don't want it to be public.
fun addMissingColumnsStatements(vararg tables: Table, existingTablesColumns: Map<Table, List<ColumnMetadata>>, withLogs: Boolean = true): List<String>
Description
Detailed description:
Restructure code in
MigrationUtils
andSchemaUtils
.To avoid calling
currentDialect.tableColumns(*tables)
inMigrationUtils.statementsRequiredForDatabaseMigration
twice.SchemaUtils
andMigrationUtils
reside in separate modules and need to share non-public functions, so using a common abstract base class with protected functions in theexposed-core
module is the most effective and clean solution. For the functionsaddMissingColumnsStatements
anddropUnmappedColumnsStatements
, two corresponding private functions with a different signature were created, with the difference being that the new functions expectexistingTablesColumns
to be passed as a parameter. Since the new privateaddMissingColumnsStatements
function is common to bothSchemaUtils
andMigrationUtils
, it was placed inBaseSchemaUtils
, and the same thing was done for thelogTimeSpent
function.Type of Change
Please mark the relevant options with an "X":
Updates/remove existing public API methods:
Affected databases:
Checklist
Related Issues