Problem with tagging (bug?)

After experimenting for a while, I finally came to the conclusion that the tagDatabase action does not do what I want/hope/expect it to do.  The problem is that it applies tags based purely on the date that changesets were applied, rather than the actual order in which they were applied.  This works fine if there is only one tag operation per update, but if tagDatabase gets called multiple times during the same run, the last tag wins.

For example, consider a changelog containing the following changesets:

  • create table X
  • tag “v0”
  • create table Y
  • tag “v1”

If I run this on an empty database, I expect the first statement to be tagged “v0”, the second and third to be tagged “v1”, and the fourth to be untagged.  Instead, the first three are all tagged “v1”, making it impossible for me to roll back to the point after I create table X but before I create table Y (using tags, that is).

Is this a bug?  Looking at the generated SQL, it appears there might be an easy fix.  Instead of updating ALL rows for the given date:

UPDATE DATABASECHANGELOG SET TAG = ‘v1’ WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM (SELECT DATEEXECUTED FROM DATABASECHANGELOG) AS X);

what if it only updated those rows with NULL tags:

UPDATE DATABASECHANGELOG SET TAG = ‘v1’ WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM (SELECT DATEEXECUTED FROM DATABASECHANGELOG) AS X) AND TAG IS NULL;

We can’t just do the null check, because there are times you may want to override existing tags. 

We did make changes in the upcoming 2.0 release to add an additional “sequence” column that tracks the actual order executed in, besides the execution date which solves the problem because we can search by max dateexecuted order by sequence desc.  2.0 should be out by the end of the month.

Nathan

Also, your example may work depending on the time resolution in  your database, and how long it takes to get from tag v0 to tag v1.

Nathan

Running 2.0.1 I see the behavior as described by ‘mrbandur’.  I would not expect all previous tags to be updated – the tag concept (at least in scm terms) is to mark a point in time.  I am running the updates from the command line with sever seconds between invocations – with each subsequent run the most recent as well as the prior entry in the changelog are updated.  I am not clear on how to view the sql other than spy or something – looking into that.  If I run from the command line I observe what I believe to be the proper behavior in that only a single row is updated.

I can see that my description is lacking detail.


I have one master, it includes 2 files each with a single change set that looks like:


include one:

   <changeSet id="1.0.1" author="xyz">

      <tagDatabase tag="version_1.0" />

   </changeSet>


   <changeSet id="1.1.1" author="xyz">

      <tagDatabase tag="version_1.1" />

   </changeSet>


setting the log-level to debug produces the following:


....

DEBUG 2/15/11 11:53 AM:liquibase: Reading ChangeSet: /Users/cporter/projects/central/server/modules/entity/schema/1.0/changelog/db.changelog-1.0.xml::1.0.1::wsi::(Checksum: 3:c941bfa2847e72a8290ff6f9259f9886)

DEBUG 2/15/11 11:53 AM:liquibase: Executing Statement: liquibase.statement.core.TagDatabaseStatement@7eb5666

DEBUG 2/15/11 11:53 AM:liquibase: Executing EXECUTE database command: UPDATE databasechangelog SET TAG = 'version_1.0' WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM databasechangelog)

DEBUG 2/15/11 11:53 AM:liquibase: Tag 'version_1.0' applied to database

INFO 2/15/11 11:53 AM:liquibase: ChangeSet /Users/cporter/projects/central/server/modules/entity/schema/1.0/changelog/db.changelog-1.0.xml::1.0.1::wsi ran successfully in 17ms

DEBUG 2/15/11 11:53 AM:liquibase: Reading ChangeSet: /Users/cporter/projects/central/server/modules/entity/schema/1.0/changelog/db.changelog-1.1.xml::1.1.1::wsi::(Checksum: 3:6677dae14b361685769f510959b9b6ef)

DEBUG 2/15/11 11:53 AM:liquibase: Executing Statement: liquibase.statement.core.TagDatabaseStatement@27b4c1d7

DEBUG 2/15/11 11:53 AM:liquibase: Executing EXECUTE database command: UPDATE databasechangelog SET TAG = ‘version_1.1’ WHERE DATEEXECUTED = (SELECT MAX(DATEEXECUTED) FROM databasechangelog)

DEBUG 2/15/11 11:53 AM:liquibase: Tag ‘version_1.1’ applied to database

INFO 2/15/11 11:53 AM:liquibase: ChangeSet /Users/cporter/projects/central/server/modules/entity/schema/1.0/changelog/db.changelog-1.1.xml::1.1.1::wsi ran successfully in 9ms


All tags are set to version_1.1 post execution.  If I run the SQL directly (btw:PostgreSQL/8.4) only a single row is updated.


Instead of using date would it be possible/viable to use the ‘orderexecuted’ column?


Thanks.

cp


I believe this is tracking at: http://liquibase.jira.com/browse/CORE-842.