-
Notifications
You must be signed in to change notification settings - Fork 356
Initial Data Model for Schema SQL Generation #1481
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
Conversation
Initial model for generating schema SQL. Closes #1478
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.
A change like this is hard to review since it doesn't really create a usable feature.
For a better change "usable" can be considered rather broadly. For example I'd consider a schema generator that creates a schema consisting of a single table with correct name for each aggregate and with a single dummy column usable. It can be invoked by a user and produces something at least somehow useful.
In such a change one can take a look at the underlying model and form an opinion if the underlying model is fit for purpose.
With the current model this is mostly guess work.
As for the merge target: We should not merge into main
until we have something that is really usable for the enduser. Basically something we/you would be willing to present as a new feature of Spring Data JDBC.
Until we have that everything should happen on the feature branch, and we don't need formal PRs.
Let's discuss further details about how to proceed in person.
* Method to build a data model of Tables/Columns and their relationships | ||
* that will be used in SQL Generation. | ||
*/ | ||
public SchemaSQLGenerationDataModel generateSchemaSQL() { |
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 don't think the mapping context should create a SchemaSqlGenerationDataModel
instead a mapping context should be used to create such a model. Either in the constructor of the class or in a factory.
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.
About to push up a change for this. Code definitely looks cleaner with this!
private Class<?> type; | ||
private boolean nullable; | ||
|
||
public String getName() { |
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.
Things like column and table names should be SqlIdentifier
since we need to consider quoting and identifier processing.
this.name = name; | ||
} | ||
|
||
public Class<?> getType() { |
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 don't see why we would need a type
in the sense of a Class
. This information is provided by PersistentProperty
. Instead we might need a type like Text
or Number
which represents database types, while abstracting over the database specific representations of those. Possibly by using Liquibase abstractions, if those exist.
...n/java/org/springframework/data/relational/core/mapping/schemasqlgeneration/ColumnModel.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
@Table | ||
static class Luke { |
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.
The choice of testdata names doesn't help to understand why these look the way they do look.
I consider names like EntityWithMultipleColumns
or stringProperty
and so one more expressive.
|
||
TableModel t1 = model.getTableData().get(0); | ||
assertThat(t1.getName()).isEqualTo("luke"); | ||
assertThat(t1.getColumns().get(0).getName()).isEqualTo("force"); |
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.
This and the following three assertions basically test the same thing.
Going to convert the Pull Request to a Draft |
public class SchemaSQLGenerator { | ||
|
||
private final IdentifierProcessing identifierProcssing; | ||
public SchemaSQLGenerator(IdentifierProcessing identifierProcessing) { |
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.
Is there a way to get the IdentifierProcessing from the RelationalMappingContext? (or when user's use this class to generate SQL - that they can easily get an IdentifierProcessing object - that matches the one they are using for executing SQL)?
For the Unit Test(s) I think passing it in gives flexibility.
@@ -29,16 +29,16 @@ public class ColumnModel implements Serializable { | |||
@Serial | |||
private static final long serialVersionUID = 1L; | |||
private final SqlIdentifier name; | |||
private final Class<?> type; | |||
private final String type; |
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.
Decided to simplify the model to be a String value. Whatever is in here is what gets in the generated SQL.
@@ -56,7 +62,9 @@ public SchemaSQLGenerationDataModel(RelationalMappingContext context) { | |||
|
|||
while (iter.hasNext()) { | |||
BasicRelationalPersistentProperty p = iter.next(); | |||
ColumnModel columnModel = new ColumnModel(p.getColumnName(), p.getActualType()); | |||
ColumnModel columnModel = new ColumnModel(p.getColumnName(), | |||
typeMapper.databaseTypeFromClass(p.getActualType()), |
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.
@schauder - I know initially I had wanted to modify the @column annotation to have a gazillion modifiers :-) to match what was in JPA.
After implementing the default behavior (and the change to the Column model) - I think adding just one annotation (databaseType) would be sufficient. We would let developers specify whatever they want there, and that is exactly what would be in the generated SQL.
If the user wishes to change our defaults, they can optionally subclass BaseTypeMapper. I stayed with what I think are datatypes that are supported by all Databases.
Will add more comments to the code - to document/describe to users how to extend/change behavior.
Initial Data Model for Schema SQL Generation that can generate SQL for a simple entity. Closes #1478
Initial data model for Schema SQL Generation.
If we want to have a feature branch (instead of main) that these changes get merged into, I am definitely good with that approach. Please let me know.