Hi Nathan!
I totally agree with you that changes to a database, that is used in a live application, should be reviewed before they are applied.
Unfortunately i am in the situation of being forced to automatically update the database DDL during application runtime. Its a very dirty thing to do, and i’d rather not do it but i have to. Nevertheless i think liquibase is the best candidate for the job, much better than hbm2ddl. So i will stick to it, and hope you forgive me for abusing your tool.
I dug into the liquibase source and made changes necessary to make it work for me. However i ran into troubles (as i expected) with the data types. To fix these troubles i had to make changes which affect more than just the hibernate part of the code. Therefore i did not send any patches, i can’t guarantee that it wont break the other use cases of liquibase. I’ll try to summarize the problem:
In the HibernateDatabaseSnapshot class are quite a lot of commented lines of code and //todo parts so i knew there was a reason why column.setCertainDataType was set to false.
Hibernate has the displeasing manner of setting predefined default values for things like precision, scale, length and so on, no matter what datatype the column has. Liquibase Columns (in my case coming from a MysqlDatabaseSnapshot) have a default of 0 for all data-type-related properties. (a varchar has no precision or scale, an integer has no length, etc.)
So just setting setCertainDataType to true has the effect that all columns are detected as having changed, even tough they are the same and just differ in the unused default values. How to avoid this ? My approach was “just set the properties (scale, precision, length, etc.) on the snapshot columns that are appropriate for the datatype of the hibernate column”. To do this, you need to know which properties are relevant for which types. Currently this information/logic is in the Column class inside the getDataTypeString method (or something like that, sorry if i don’t remember correctly, i don’t have any code atm). Since i needed this information, and i think this information should be more accessible to other classes, i moved it to the SQLUtil class.
Another approach would be to change the isDataTypeDifferent Method of the column to only check the difference of the properties relevant to the type but i thought it would be cleaner to only set the values if they make sense and keep the logic of isDataTypeDifferent simple.
After i made those and other small changes i also ran into the recently reported MySQL-Double-Bug, and unfortunately a couple more MySQL specific type-parameter issues. I had to change the lists of those noParens, oneParam, twoParams lists and bloat the Columns getDataTypeString method with a some more MySQL specific special cases. It works now after a lot of tweaks but it is not a sustainable solution.
It seems like it would be better to move that part into the database specific classes, i.e. the database knows if it wants one or two parameters for a type and the syntax of the type instead of having the Column maintaining lists of types and parameters and exceptions from those lists and special syntax exceptions and lots of database instanceof SomeSpecificDatabase . . .
I don’t know all differences of all the databases and versions and SQL standards, and most important, the big picture of liquibase so i don’t feel confident to make such decisions.
You’re the expert on this topic and its a decision that only you can make, thats why i did not commit or send anything.
But who knows what you have come up with in 2.0, maybe all these things have changed anyway.
Well anyway, thanks for reading and i hope i can make it to the chat tomorrow/today 