Postgres liquiabsev No inverse to liquibase.change.core.RawSQLChange - liquibase

Getting No inverse to liquibase.change.core.RawSQLChange created” while running liquibase for postgres env

Check if rollback statement is mentioned. If not just added dummy like
-- rollback select 1

Here are the ways to incidate "no rollback necessary" in liquibase changelogs:
XML:
<rollback/>
formatted SQL:
--rollback not required
YAML:
rollback:
- empty: {}

The error No inverse to liquibase change... indicates :
You have not provided rollback sql statement for the changeset
auto-rollback statement for sql statement you are using is not known
and hence Liquibase fails to rollback your changeset.
If you want to skip the rollback for a changeset, you can achieve that by the ways Daryl has mentioned in his answer.
Here are the ways to incidate "no rollback necessary" in liquibase
changelogs:
XML:
<rollback/>
formatted SQL:
--rollback not required
YAML:
rollback:
- empty: {}
Or if you want to have the rollback statements then you can include it by referring to this rollback documentation link.
You can also refer to my answer on this post for some details on liquibase rollback.

Related

Liquibase transaction rollback vs <rollback> tag

I learned that Liquibase runs each changeSet in a transaction and commits it after inserting into the DATABASECHANGELOG table.
If something goes wrong during the changeSet, the transaction gets rolled back.
My question is, what happens if the changeSet also includes a <rollback> tag.
I know that the rollback tags are used in combination with liquibase dedicated rollback commands, but which one has precedence during a regular migration, the command from the rollback tag or the transaction abortion?
The <rollback> block is not used in when an update fails. If the update fails, Liquibase just calls "rollback" on the connection and relies on the database to correctly roll things back. The <rollback> block is only used when doing the separate rollback command where we're "undoing" the changeset that was already committed in the database.
NOTE: the fact that Liquibase relies on the connection rollback to revert a failed update is why you have to be careful if you have multiple statements in the same changeSet. If you have two createTable calls and your the database auto-commits after the first and the second fails, the rollback on the connection will not roll back the first table. So when you run update the next time, you'll get a table already exists error from the first createTable. The rules on exactly what statements auto-commit are database-specific, so the good rule of thumb is "only one statement per changeset"

Rollback tag for DROP table if exist condition

What would be the rollback of droptable:
- changeSet:
id: 1
author: vikas
changes:
- sql:
sql: DROP TABLE IF EXISTS `adapter`
What should I put in rollback for the above changeset.
I am getting below error when I was trying to rollback without having rollback tag:
Error setting up or running Liquibase: liquibase.exception.RollbackImpossibleException: No inverse to liquibase.change.core.RawSQLChange created
The error
Error setting up or running Liquibase: liquibase.exception.RollbackImpossibleException: No inverse to liquibase.change.core.RawSQLChange created
happens because you use raw sql, and not the appropriate tag for it (it would be dropTable), so liquibase doesn't know what to do with it. It can't create a rollback.
Also, the documentation says that
Other refactorings such as “drop table” and “insert data” have no corresponding rollback commands that can be automatically generated. In these cases, and cases where you want to override the default generated rollback commands, you can specify the rollback commands via the tag within the changeSet tag. If you do not want anything done to undo a change in rollback mode, use an empty tag.
So you'll have to create a proper rollback for drop table operation.

What all the steps Liquibase follows while rolling back?

I don't understand the detailed steps when rolling back using Liquibase.
I had scenario like 6 changesets and for one changeSet rollback was not defined - that is, only <rollback/> within the changeset.
After executing using deployIT I could see 7 entries in Databasechangelog table, 6 for added, one for tag creation due usage of deployIT.
After rolling back I saw the behavior of removing all newly added 6 changesets even though one of the six changesets had an empty rollback tag.
Please any expert tell me why? What is the exact behavior of rollback?
Overall want to know when records from Databasechangelog removed ?
When running rollback, liquibase finds the changeSets to roll back, and then checks for a <rollback> tag in each describing how to roll the changeSet back.
If there is no <rollback> tag, then Liquibase checks if the changes in the changeSet have built-in logic on how to roll themselves back. Like gile pointed out, if there is enough information in the change to undo it (like how the createTable change has the table name needed to drop the table) it will be able to still roll them back.
But if there isn't enough information in the change (like how a dropTable doesn't have the information needed to re-create the table) then the rollback command will fail with a "cannot roll back" error.
So the rollback logic is:
Use what is defined in a block
If no rollback block, try to deduce what is needed
If there isn't enough information to roll back, exit before rolling back
If you specify an empty rollback block, you are telling Liquibase "the logic needed to roll this back is to do nothing", so Liquibase happily runs your no-op rollback command and marks the changeSet as rolled back.
Depending on your change sets, may be you fall in case of statements having rollback commands generated automatically, as for Liquibase Rollback documentation:
Many refactorings such as “create table”, “rename column”, and “add
column” can automatically create rollback statements. If your change
log contains only statements that fit into this category, your
rollback commands will be generated automatically.
Other refactorings such as “drop table” and “insert data” have no
corresponding rollback commands that can be automatically generated.
In these cases, and cases where you want to override the default
generated rollback commands, you can specify the rollback commands via
the tag within the changeSet tag. If you do not want anything done to
undo a change in rollback mode, use an empty tag.
At http://forum.liquibase.org/topic/understanding-rollback you can find more details and other links.

Liquibase rollback to tag

I am new to Liquibase and I am trying to get the rollback feature working. I am running Liquibase in Windows. I executed an install which tagged the database at version_1.0. I ran an update which tagged the database at version_1.1. Now I am trying to rollback to version_1.0
Here is the command I am running:
liquibase rollback version_1.0
this gives an error that a --changeLogFile is needed so I ran this
liquibase --changeLogFile=v001/master.xml rollback version_1.0
I provide the name of the change log file that was executed during the update, but nothing gets. The update contains 2 create table statements and the tables were not dropped. What am I missing in the rollback process?
Liquibase does not tag the database really. It only tags to know which changessets need to be rolled back.
The rollback will be done by execute the rollback tags in the changeling.

How to rollback an implicit SSMS transaction (statement with go at the end)?

Question:
Normally, you can undo a sql command with rollback.
BEGIN TRY
BEGIN TRANSACTION
/* run all your SQL statements */
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
My question now:
If 'one' did this
UPDATE TABLE_X SET FIELD_X = 'bla'
GO
in SSMS (notice the go at the end) and forgot to specify the WHERE clause,
is it possible (and how) to rollback the implicit transaction that SSMS executed this command in (statements with go at the end are implicitly executed in a transaction) ?
Note:
I didn't do that, but a colleague of mine did a few days ago (without go).
I undid the damage he did (fortunately I made a backup 0.5 hours before he did that), but for the future, it would be good to know this, because this happened to me once, too.
No, you can't, not easily. Restoring from backup is the best option.
see the link below, I think it will help you
How to recover the old data from table
thanks
Arun
GO does not specify the end of an implicit transaction, but the end of a batch. That's why you won't be able (unfortunately) to ROLLBACK your UPDATE after a GO.
From the MSDN page on GO:
GO is not a Transact-SQL statement; it is a command recognized by the
sqlcmd and osql utilities and SQL Server Management Studio Code
editor.
SQL Server utilities interpret GO as a signal that they should send
the current batch of Transact-SQL statements to an instance of SQL
Server. The current batch of statements is composed of all statements
entered since the last GO, or since the start of the ad hoc session or
script if this is the first GO.
The UPDATE command will only be seen as the start of an implicit transaction if you have specified SET IMPLICIT_TRANSACTIONS ON; (see here). In that case, a number of commands (CREATE, DELETE, UPDATE etcetera) will automatically start a new implicit transaction, and that transaction will not end until you issue a ROLLBACK or a COMMIT.
(See for more info on the difference between transactions and batches in SQL Server for example this question on ServerFault: SQL Server: Statements vs. Batches vs. Transactions vs. Connections.)