Skip to content
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

Changes to support generating Liquibase change-sets #1520

Closed
wants to merge 32 commits into from
Closed

Conversation

kurtn718
Copy link
Contributor

  • You have read the Spring Data contribution guidelines.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

@kurtn718 kurtn718 requested review from mp911de and schauder May 22, 2023 12:44
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label May 22, 2023
@@ -32,12 +32,12 @@
* @author Kurt Niemi
* @since 2.0
*/
class DerivedSqlIdentifier implements SqlIdentifier {
public class DerivedSqlIdentifier implements SqlIdentifier {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to alternatives if we don't want to make this public.

The TableModel and ColumnModel classes take in a SQLIdentifier in their constructor - and the LiquibaseChangeSetGenerator class creates a SchemaSQLGenerationModel (which I think I am going to rename/refactor to SchemaModel)

Copy link
Member

@mp911de mp911de left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did a first review pass.

@@ -70,6 +70,17 @@
</roles>
<timezone>+1</timezone>
</developer>
<developer>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should clean up the developer sections as these information are inherited from parent pom's.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, all of the developers should go into the parent spring-data-relational.pom? (and we remove from the spring-data-jdbc and spring-data-r2dbc) and also make sure that nobody gets deleted :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly. I assume that we missed the cleanup when we split modules and added the R2DBC module during the course of our repository rearrangement one or two years ago.

continue;
}

SqlIdentifier tableName = new DerivedSqlIdentifier(table.getName(), true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usage of DerivedSqlIdentifier isn't appropriate. DerivedSqlIdentifier is intended to be used when creating a SQL model from Java classes. In this case, we have already a proper SQL model. I'm also not quite sure whether quoted should be part of the identifier handling as we're working with plain table and column names.

for (liquibase.structure.core.Table table : tables) {

// Exclude internal Liquibase tables from comparison
if (table.getName().startsWith("DATABASECHANGELOG")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have a table filter Predicate to keep things extensible.

this.targetDatabase = targetDatabase;
}

public void generateLiquibaseChangeset(String changeLogFilePath) throws InvalidExampleException, DatabaseException, IOException, ChangeLogParseException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use Spring's Resource abstraction instead of Strings. With string values, we can never know, whether these could be URL's, resource paths or file paths.

setIdentifierColumns.add(p);
}

iter =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By iterating over persistent properties, we should get all properties. We would need to ensure that properties aren't associations or entities. We should not require @Column.

import java.util.ArrayList;
import java.util.List;

public class TableDiff {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be able to use Java records for all pure data objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converted all of the pure data objects to use records. It's definitely cleaner - removing the getters/setters.


// Identify deleted tables
Set<TableModel> deletedTables = new HashSet<TableModel>(sourceTableData);
deletedTables.removeAll(targetTableData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful. Databases may contain tables that are not mapped. If we remove those tables, then we might delete their data. Another safeguard (predicate) would be good, to either have a boolean flag or a predicate to identify the tables, that can be deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still have the safe-guard in that we don't automatically apply the change set, but having user(s) modify the changeet to remove the deletions every time would be annoying :-) and also error prone.

I like the predicate idea - with the default implementation we don't delete anything, and then it's on the developer if they supply a custom predicate.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mp911de - Hi, I think I've pushed up changes for everything that you had mentioned.

@mp911de mp911de self-requested a review May 30, 2023 14:29
@kurtn718 kurtn718 marked this pull request as ready for review May 31, 2023 17:19
Reformat code, switch to tabs. Accept property in DatabaseTypeMapping to provide more context to the type mapping component.

Rename LiquibaseChangeSetGenerator to …Writer as we're writing a changeset and computing the contents is a consequence of writing a changeset. Refine naming to express what we're actually doing.

Introduce setters for enhanced configuration of predicates. Reduce visibility of types to avoid unwanted public API where public access is not needed.

Remove usused code, move methods around for improved grouping of code.
Rename package to schema as the schema is being created and updated and not generated. Rename …Model classes to just their name as types are package-private and not visible externally. Refactor SchemaDiff to Java record.

Use different overloads to write schema changes to avoid LiquibaseException leaking into cases where no diff is being used. Introduce SchemaFilter to filter unwanted mapped entities.

Add tests for changeset-creation.
@mp911de mp911de added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Jun 2, 2023
@mp911de mp911de self-assigned this Jun 2, 2023
Move code to JDBC module. Introduce comparator strategy to customize how table and column names are compared.
mp911de pushed a commit that referenced this pull request Jun 6, 2023
We now support schema creation and schema migration by generating Liquibase changesets from mapped entities. We also support evolution of schema by comparing existing tables with mapped entities to compute differential changesets.

Closes #1478
Original pull request: #1520
mp911de added a commit that referenced this pull request Jun 6, 2023
Reformat code, switch to tabs. Accept property in DatabaseTypeMapping to provide more context to the type mapping component.

Rename LiquibaseChangeSetGenerator to …Writer as we're writing a changeset and computing the contents is a consequence of writing a changeset. Refine naming to express what we're actually doing.

Introduce setters for enhanced configuration of predicates. Reduce visibility of types to avoid unwanted public API where public access is not needed.

Remove usused code, move methods around for improved grouping of code.

Rename package to schema as the schema is being created and updated and not generated. Rename …Model classes to just their name as types are package-private and not visible externally. Refactor SchemaDiff to Java record.

Use different overloads to write schema changes to avoid LiquibaseException leaking into cases where no diff is being used. Introduce SchemaFilter to filter unwanted mapped entities.

Move code to JDBC module. Introduce comparator strategy to customize how table and column names are compared.

See #1478
Original pull request: #1520
mp911de added a commit that referenced this pull request Jun 6, 2023
See #1478
Original pull request: #1520
@mp911de mp911de added this to the 3.2 M1 (2023.1.0) milestone Jun 6, 2023
@mp911de
Copy link
Member

mp911de commented Jun 6, 2023

That's merged and polished now.

@mp911de mp911de closed this Jun 6, 2023
@mp911de mp911de deleted the issue-1480 branch June 6, 2023 06:50
@mp911de mp911de linked an issue Jun 6, 2023 that may be closed by this pull request
mp911de pushed a commit that referenced this pull request Jun 6, 2023
We now support schema creation and schema migration by generating Liquibase changesets from mapped entities. We also support evolution of schema by comparing existing tables with mapped entities to compute differential changesets.

Closes #756
Original pull request: #1520
mp911de added a commit that referenced this pull request Jun 6, 2023
Reformat code, switch to tabs. Accept property in DatabaseTypeMapping to provide more context to the type mapping component.

Rename LiquibaseChangeSetGenerator to …Writer as we're writing a changeset and computing the contents is a consequence of writing a changeset. Refine naming to express what we're actually doing.

Introduce setters for enhanced configuration of predicates. Reduce visibility of types to avoid unwanted public API where public access is not needed.

Remove usused code, move methods around for improved grouping of code.

Rename package to schema as the schema is being created and updated and not generated. Rename …Model classes to just their name as types are package-private and not visible externally. Refactor SchemaDiff to Java record.

Use different overloads to write schema changes to avoid LiquibaseException leaking into cases where no diff is being used. Introduce SchemaFilter to filter unwanted mapped entities.

Move code to JDBC module. Introduce comparator strategy to customize how table and column names are compared.

See #756
Original pull request: #1520
mp911de added a commit that referenced this pull request Jun 6, 2023
See #756
Original pull request: #1520
@mp911de mp911de linked an issue Jun 6, 2023 that may be closed by this pull request
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Integrating with Liquibase - Generating Changesets Schema generation [DATAJDBC-536]
3 participants