loading...

Liquibase: Don't use ISO dates as changeset ids with yml

sgmoratilla profile image Sergio Garcia Moratilla ・2 min read

After upgrading a service from java 8 to java 11, our liquibase got crazy and tried to apply every change to the database from the beginning. But they were already applied and no changes were made to the database.
We discovered that using ISO dates as identifiers of the changeset was a bad idea. The hard way.

 Liquibase Changesets

Changesets in liquibase are, as their name implies, a set of changes that must be applied at once in a database (or not at all).

In order that liquibase is able to distinguish when a changeset is already applied or not, it requires you to set a unique identifier.

By convention, we started to use the ISO date when the change was written (format yyyy-mm-dd).

For example:

databaseChangeLog:
- changeSet:
    id: 2019-06-06
    author: sergiomoratilla
    comments: Adding new value to know which client was used to book.
    changes:
    - modifyDataType:
        tableName: reservation
        columnName: client
        newDataType: ENUM('WEB_DESKTOP', 'WEB_MOBILE', 'APP_ANDROID', 'APP_IOS', 'UNKNOWN') NOT NULL

Liquibase stores the applied changeset in a table called DATABASECHANGELOG within your schema. So that, we were expecting a row

"2019-06-06"    sergiomoratilla /liquibase/changelogs/this-example.yml ...

It's a trap

Liquibase's YML parser decides to get the changeset id as a Date, and then use toString() to generate the id. That smells because you don't have control on that format... and this is exactly what happened.

Instead of storing "2019-06-06" we got "Wed Jun 06 00:00:00 GMT 2019".

After upgrading to Java 11, the behaviour of toString() changed and now returns "Wed Jun 06 02:00:00 CEST 2019". It is exactly the same date so that this format is correct but it is a bit weak to trust your ids to default formatting.

 Solutions

Don't use ISO date as ids (if you are using yml format to configure that). Probably, most of you didn't already do that.

When we started to have several changes on the same date, we decided to change that format to yyyymmdd-n, where n is an incremental integer.

What if you are already using them? I suggest you to replace the ids in your changelogs files by the ids you already have in your database. And change your convention for new files!

Discussion

pic
Editor guide