Fork me on GitHub

n. Slang a rough lawless young Kuali developer.
[perhaps variant of Houlihan, Irish surname]
kualiganism n

Blog of an rSmart Java Developer. Full of code examples, solutions, best practices, et al.

Friday, September 16, 2011

Liquibase: Semi-Database Agnostic Changelogs


Changelogs in Liquibase are typically RDBMS specific. For a database change management system that advertises being database agnostic, it is pretty weird to still be writing changelogs that are database specific. For example, check this out:

Above is a changelog specific to MySQL. You can tell because of the VARCHAR type used. If it were Oracle, that would probably be a VARCHAR2

This makes it a little difficult to reuse changelogs across database platforms. End up locked into one database platform which is a bit troublesome for projects that use more than one (or support more than one like Kuali).

Semi-Database Agnostic Changelogs

Not all RDBMS-specific issues can be corrected. Liquibase suggests using contexts in these kinds of scenarios. However, it is possible to directly address the field type issue. Liquibase supports generic SQL Types defined in the java.sql.Types class. Here's an example:

You start seeing java.sql.Types.VARCHAR(30) where the 30 is the length of the field. This will work in Oracle as well. The java.sql.Types.VARCHAR refers to the field in the Java API. During processing, Liquibase will substitute the native Oracle type for the java.sql type.

Generating Semi-Database Agnostic Changelogs

You may be asking right away, "Why do you want to generate changelogs? Why not just have developers maintain them?" I've tried this method before, and I found it distracting and cumbersome for developers to duplicate work on changelogs. Whenever a database is modified, then the install changelog and the update changelogs need to be modified. The install changelog is to recreate the database, and the update change log is for updating existing databases. Indeed, this does eliminate the "Master database" antipattern, but it forces some extra effort and testing. I've found this to be unnecessary. I much rather prefer and recommend sticking with the "Master database" antipattern. Just apply update scripts to your "Master" and run generate changelogs against it. Since liquibase is database agnostic, we should get the same changelog from any database and be able to apply it to any other database; therefore, it doesn't really matter which database is used as the master.

The Problem

Of course, anyone can start doing their changelogs differently to support the new types, but what about when you generate your changelogs? Well, Liquibase will just use the standard RDBMS targeted changelogs. You could just do post-processing on your changelogs and cleanup after generating.

The Solution

I have put together some Liquibase extensions to get around this. They are in a Git Hub repository. Anyone can download or check them out. You simply put them into your classpath when you run Liquibase, and it will load the extensions automagically. Among the extensions are numerous fixes for generalizing changelogs. One very prominent one is the lack of sequence support in MySQL databases. Even though MySQL does not require sequences, Kuali does use sequences. This causes conflict. It is especially the case when generating changelogs.

For examples on how to use the extensions, you can look at my other github project lbcopy. it's a database copy tool based on Liquibase. It can export/import databases as well as directly migrate from one to another.

1 comment:

  1. This came up on which nicely linked to this page, but got rid of the formatting...