Liquibase: runOnChange + rollback - liquibase

According to Liquibase docs stored procs/triggers etc should be stored separately in a single copy and added to changeset with runOnChange to update them for each change. But what is a recommended way to rollback to the previous change? The only idea that I have is to copy them to a separate folder for each release and add apply operation of this version as a rollback (for example, have sql\procs\current for last version all added to changelog as apply and sql\procs\1.0.0 is a copy of sql\procs\current when we started new 1.0.0 release). Are there any best practices for it?
Thanks!

We keep single copy of replaceable objects (procs/triggers/views etc)
and use version control system (VCS) - git in our case.
When you want to rollback to previous version, just revert to relevant commit in VCS and run liquibase update.
Tutorial using Oracle - we are working by this tutorial for two years.

Related

Liquibase: How do I manage different branches with one database

I have the following problem:
I am working on two different branches: dev, feature1
Both branches work on the same database schema.
Imagine I have changelog-v1.0 on my dev-branch und my database fits to that version.
Now if I have changelog-v1.1 on my feature1-branch and start my app from there liquibase will apply thhis changes to my database.
From this moment on my app on dev-branch will not work anymore, because even though there is no changelog-v1.1 on the dev-branch, the database is already migrated to that version
and if I start my app on the dev-branch liquibase will not roll back the changes of changelog-v1.1.
Working on many branches with different changelog but just one database.
How do I manage this?
You can have a master changelog file pointing to children changelog files. But need to make sure to have same files in all branches that have to be merged from dev to feature branch.
Also, note that you have rollback code and tagging in the liquibase changesets in order to successfully rollback changes.

Liquibase diffChangelog does not generate rollback

If I haven't misunderstood anything, the liquibase command diffChangelog should be able to generate rollback change sets for some types of change sets like create table, rename column or add column but it is not working for me using the liquibase gradle plugin version 2.0.2. Running a command like this:
./gradlew diffChangelog -PrunList='diffLocal' -PchangeLogFile='changelog1.mysql.sql'
generate create tables change sets fine but it does not add the rollback part. Did I misunderstood that Liquibase is able to do that for me?
I am using liquibase-core version 3.8.9 and liquibase-groovy-dsl version 2.1.1. I have tried many change log file formats like xml,yaml,groovy and json but none of them adds the rollback. Even with a License Key PRO rollbacks are not added.
Any idea?

Does liquibase have a method to test a rollback strategy without actually executing it?

I am brand new to Liquibase...
Today I wrote a Liquibase changeset using --liquibase formatted sql.
I created two tables where the second had a foreign key dependency on the first.
My rollback strategy was (mistakenly) drop table1; drop table2. When I ran the update and tested the rollback it failed because of the foreign key constraint. However, when I corrected my mistake and attempted to rerun it, it failed because the checksum didn't match.
I know that the obvious answer is to make more atomic changesets, however...
Does Liquibase support a way to test this sort of thing without actually running it so I can avoid the problem with the checksum on the edited rollback?
Failing that: is there a workaround for the checksum problem that will let me edit my files after running the update? (ctrl+z?)
The short answer to your question is, no Liquibase doesn't have such a thing.
Liquibase is a great toolkit, but it doesn't have a lot of bells and whistles, and it doesn't have much of an 'opinion' on how it should be used, or what your workflow should be. In your case, I would suggest that one way to deal with the problem is to just drop the database and then re-create it from the changelog. If you have already deployed the changelog in multiple places, that might not be possible, and if you weren't prepared to do that, that could be a problem.
There is an option to specify a validChecksums attribute on a changeset, so you could use that, but in general if you are using that you are making your changelog more complicated.
If you wanted to look at something that is more full-featured and that has the ability to forecast changes before they are deployed, please check out my company's product, Datical DB. It uses liquibase at its core, but adds a whole lot more (and is priced accordingly).
Liquibase provides updateTestingRollback command that basically updates the database, then tests its rollback and if successful, applies the changes again.
Your problem with invalid checksums may be solved with clearCheckSums command. It removes current checksums from database and on next update change sets that have already been deployed will have their checksums recomputed, and change sets that have not been deployed will be deployed.
For more details check Liquibase commands.

Run liquibase rollback without changelog files?

Liquibase is not able to rollback a without the changelog files.
It requires to provide the original changelogs/changesets files when running a rollback.
My questions is: Is there any way to run rollback without the files?
E.g.: Store the files (or rollback commands) in the databasechangelog table?
You could use Liquibase's "Future Rollback SQL" feature. It's exposed in several different ways.
Java API
Liquibase.futureRollbackSQL(...)
Spring Integration
SpringLiquibase.setRollbackFile(...)
Maven Integration
mvn liquibase:futureRollbackSQL
Ant Integration
<liquibase:rollbackFutureDatabase outputfile="/path/to/rollback-future.sql".../>
Command Line
liquibase futureRollbackSQL
If you use this feature in conjunction with update or updateSQL then you will be able to rollback the update without the original change logs.
As far as I know liquibase generates the rollback commands on the fly from the changesets (in those cases where this is possible).
So it will always need the changelog files to do this.
I dont't think that there is an easy solution to do this. The whole point of liquibase is to keep the changesets in separate files, so you can put them in some sort of version control system.

Can you control Liquibase updateSQL output by major release?

We use liquibase to generate database changes but need these scripted into SQL files because our DB server has neither Liquibase nor even a JVM installed.
We use the updateSQL command to create the DDL script needed to make changes, however if we run (on our development server) a 'dropAll' first we get a change set for every release.
Is there a way to run Liquibase regular 'update' for one collection of changesets (i.e. all prior releases) and then produce updateSQL output only for the last release? Essentially can we parameterize our build process to indicate the release we are targeting and automatically produce only SQL for that release?
Thanks
We have a similar setup.
The way we handle this is we have an "integration" db that always keeps the last official release.
When we have a new release candidate we let liquibase run (updateSQL) against that integration DB. Since it is on the last (resp. the current) release, updateSQL will only write out the difference between the new release candidate and the last release.
So you have a delta ddl that needs to be applied to go from release x to y.
Once the release candidate is released we let liquibase also update the integration db.
There are several ways to run a portion of your changelog.
If you break up your changelog files using versions (changelog-1.0.xml, changelog-1.1.xml, changelog-2.0.xml) and then have a master changelog.xml that <include>'s them, then the easiest solution for you may be to just run updateSql passing in the changelog version you want. If you want to generate sql for the entire database, run "liquibase --changelogFile=master.changelog.xml updateSql". If you want to generate sql for just version 2.1, run "liquibase --changeLogFile=changelog-2.1.xml updateSql"
#Jens answer works well and is what I often suggest. It has the advantage compared to the above option of catching new changeSets that were introduced into old changelog versions through a merged in patch release, for example.
Beyond that, you could use context or preconditions to dynamically control what is ran. Depending on your setup there may be ways to get those to work well for you.
Finally, there is always the extension system where you can write custom logic around how changelogs are parsed and executed to pull out older version changeSets based on file name or some other mechanism that works for you.