More automatic rollback support

I have idea how to implement automatic rollback support for some refactorings.

For example dropUniqueConstraint:
At first sight it seems that liquibase cannot rollback dropping of constraint, because it doesn’t know constraint definition - only constraint name from element.

But, while performing dropUniqueConstraint change, it’s easy to get actual constraint definition from database and store it in databasechangelog.
So while performing rollback dropUniqueConstraint change can read such definition from databasechangelog and recreate constraint.

In such way, it’s possible to add automatic rollbacks for other changes:
Drop View
Drop Sequence
Drop Default Value
Drop Foreign Key Constraint
Drop Primary Key Constraint
Drop Index

and with some restrictions (no data recovery):
Drop Table
Drop Column

In general, Change should have possibility to store some data in databasechangelog and get it back in generateRollbackStatements.

The reason we don’t generate automatic rollback options from those type of changes is because you can’t always trust the state information you have.  For example, if you are running in rollbackSql mode (where it generates rollback sql but doesn’t actually execute it) you cannot take a database snapshot to fetch the metadata because there may have been modifications that were not really applied but should affect the change information.

For example, if you have (not the best changelog, but it happens…):

  1. create table person (id, name)
  2. drop table person
  3. create table person (id, firstname, lastname)

If you rollback to step 1 and try to automatically generate a createTable command based on the current state of the database you would end up with a table with id/firstname/lastname, not just id/name like the changelog would suggest.

You also can’t go off of the changelog because, while you could write something to “apply” changes based on standard change tags, that scheme breaks down when there are tags and custom change tags because you cannot know what is going on there.

There may be many cases where you can determine automatic rollback commands, but since there are cases where you cannot, I do not want to add it into the core product.  It may be useful to add it as an extension, however.

Nathan

OK. rollbackSql and updateSql are problematic, but many people use update and rollback online.
And in this case automatic rollback could be possible:

According to your example:
liquibase update:

  1. executing create table person (id, name):
    (store in databasechangelog nothing)
    execute create table person (id, name) sql
  2. executing drop table person:
    fetch current person table definition (person (id, name)) and store in databasechangelog
    execute drop table person
  3. executing create table person (id, firstname, lastname):
    (store in databasechangelog nothing)
    execute create table person (id, firstname, lastname) sql

liquibase rollbackCount 2
3. executing rollback for create table person (id, firstname, lastname):
execute drop table personsql
2. executing rollback for drop table person:
fetch previous table definition from databasechangelog  and
execute create table person (id, name) sql

What’s the problem?

(Of course data are lost, so drop table is special case, but for example drop constraint can be in 100% reverted).

Even if there were another change between 1. and 2. changing person table (for example alter table person add column address varchar(100)</sql), correct table definiition will be captured just before performing drop table.

I agree that it may be supported as an extension, but now it’s hard to implement, because extension must somewhere store data. So please add possibility for Change to store own data in databasechangelog (String) and fetch it again while generating rollback statements.

Damian

I created an feature request for it http://liquibase.jira.com/browse/CORE-423 and assigned it to 2.0.  We’ll see how it fits in with everything else we are trying to get in for 2.0

Thanks for the suggestion, it is a very good idea.

Nathan