liquibase : execute a changeset each time I run the application - liquibase

I am using liquibase to load data in my Mysql database like this :
<loadUpdateData encoding="UTF-8"
primaryKey="pk_id"
file="config/liquibase/site.csv"
separator=";"
tableName="site">
<column name="site" type="STRING"/>
</loadUpdateData>
How can I force liquibase to execute this task each time I run my application (in case site.csv has changed)? My problem is that when liquibase has executed the changeset, it won't execute it again.

If you only want to run it if the CSV file has changed, add runOnChange="true" as an attribute to the to the changeSet.
<changeSet id="42" author="arthur" runOnChange="true">
<loadUpdateData>
...
</loadUpdateData>
</changeSet>
If you always want to run it, use runAlways="true" instead.
See the manual for more details:
http://www.liquibase.org/documentation/changeset.html

Related

Can I pass a CSV file as command line argument to <Loaddata> in Liquibase? If not, is there any other way to do it?

is there a way to pass the TEST.csv value from the command line
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(1) FROM tb_mt_data_map;</sqlCheck>
</preConditions>
<loadData encoding="UTF-8"
file= "TEST.csv"
separator=";"
quotchar="'"
relativeToChangelogFile="true"
tableName="tb_mt_data_map">
is there a way to pass the TEST.csv value from the command line
You can use Liquibase Property Substitution
Liquibase allows dynamic substitution of properties in changelog files. We can configure multiple properties inside a file and then use them wherever required. You can configure "csvFileName" and then use it in changesets with syntax ${csvFileName}.
You can either pass the property value from command line -DcsvFileName=Test.csv or you can configure it's value in liquibase.properties file.
csvFileName=Test.csv
Then you can use it in your changeset as follows:
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">SELECT COUNT(1) FROM tb_mt_data_map;</sqlCheck>
</preConditions>
<loadData encoding="UTF-8"
file= "${csvFileName}"
separator=";"
quotchar="'"
relativeToChangelogFile="true"
tableName="tb_mt_data_map">
For more details on property substitution, have a look at my answer on this post

can't get liquibase executeCommand changeset to do anything

From the liquibase docs, it looks like an executeCommand changeset should just shell out and execute the given command (e.g., mysqldump). But if I specify some changeset like
<changeSet author="me" id="test">
<executeCommand executable="date" />
</changeSet>
then all I get is this error message
2016-07-20 10:02:43,675 ERROR [main] liquibase
even though the changeset gets marked as EXECUTED in the db.
Even if I specify some different executable like a tiny test shell script, it doesn't look like it actually gets executed.
Is there anything else that I need to specify in the changeset, or do I have some incorrect expectation about how an executeCommand changeset should work?

Liqubase: How to trigger all scripts from the folder on changing one of them?

There're three scripts and a changelog.xml in a directory. Each script refills one table(delete * from, N lines of inserts):
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<include file="refillTable1.sql" relativeToChangelogFile="true" />
<include file="refillTable2.sql" relativeToChangelogFile="true" />
<include file="refillTable3.sql" relativeToChangelogFile="true" />
...
</databaseChangeLog>
The issue is that they have constraints on each other so I cannot drop everything from Table3 without dropping everything from Table1 beforehand, therefore when I need to refill Table3 with refillTable3.sql I need refillTable1.sql to be reexecuted too.
How can I make all three scripts reexecute when I change only one on them? I explicitly don't want to reexecute all scripts on every deploy.
Instead of using the "include" tag, I'd use the "sql" tag and put it in a changeSet.
Then, you can add "runOnChange=true" to the "changeSet" tag. The changeSet will be executed when the .sql file is updated.
<changeSet runOnChange="true" id="1" author="r2">
<sqlFile path="refillTable1.sql"/>
</changeSet>
<changeSet runOnChange="true" id="2" author="r2">
<sqlFile path="refillTable2.sql"/>
</changeSet>
<changeSet runOnChange="true" id="3" author="r2">
<sqlFile path="refillTable3.sql"/>
</changeSet>

Using Liquibase contexts to conditionally activate/deactivate a change set

We have changeset one:
--changeset change_one runOnChange:true
And changeset two:
--changeset change_two runOnChange:true context:kansas
change_one applies to all our installations but change_two only applies to our "kansas" installation. We want to ensure that change_two is executed whenever change_one is changed - how can we do this?
change_one has runOnChange:true so it will run whenever changed. But how can we ensure change_two runs when change_one executes - but only when we pass context:kansas?
When you run Liquibase without specifying any contexts, you might expect that no contexts should be activated, but in fact it works as documented in that ALL contexts will be activated. If you use contexts in your change logs to disable change sets, you will have to set a contexts parameter whenever you execute Liquibase. e.g.
mvn process-resources liquibase:update -Dliquibase.contexts=production
You should also check into the labels feature added in Liquibase 3.3. The difference is that the caller can specify some sophisticated expressions. e.g.
mvn process-resources liquibase:update -Dliquibase.labels=!kansas
Note, however, that the behavior is the same as contexts when no label expression is specified.
Example Change Sets:
<changeSet id="tag-v1" author="a">
<tagDatabase tag="v1"/>
</changeSet>
<changeSet id="tag-v1a" author="a" context="kansas">
<tagDatabase tag="v1a"/>
</changeSet>
<changeSet id="tag-v1b" author="a" labels="kansas">
<tagDatabase tag="v1b"/>
</changeSet>

Liquibase runOnChange="true" but stored function in sqlFile not updated in database for changes

I have a changeset :
<?xml version="1.0" encoding="UTF-8" ?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet id="1359722450-38" author="myname" runOnChange="true" >
<sqlFile endDelimiter="" splitStatements="false" path="sql/38_getLeadSet.sql" relativeToChangelogFile="true" />
<rollback>DROP FUNCTION `getLeadSet`</rollback>
</changeSet>
</databaseChangeLog>
which is included by a mater log files
I if change sth in sql/38_getLeadSet.sql and run liquibase update , I get :
FUNCTION getLeadSet already exists liquibase.exception.DatabaseException: Error executing SQL ... getLeadSet....
on command line. Seems to be same issue as mentions here ,but I have latest liquibase version
any kind of suggestion is appreciated , thanks
Edit
Well we need drop sql before the sql file tag e.g
<sql>DROP FUNCTION if exists `getLeadSet`</sql>
<sqlFile endDelimiter="" splitStatements="false" path="sql/38_getLeadSet.sql" relativeToChangelogFile="true" />
<rollback>DROP FUNCTION `getLeadSet`</rollback>
P.S) Liquibase Version: 2.0.5
runOnChange="true" is not working, instead I used runAlways="true" which is working.
I have decided to use runAlways="true" instead of runOnChange="true" in my project, because that doesn't make much difference for my project during the deployment.
liquibase version is 3.5.1
Are you rolling back your change before updating it again? Because the function getLeadSet would already be exisiting and you may be getting a sql error rather that a liquiabase one.