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?
Related
From command line I let liquibase run in the version 4.19.0.
liquibase --changeLogFile=update.xml update
where update.xml is a bundle of changelogs:
<databaseChangeLog ...
<include file="changelog_1.xml" relativeToChangelogFile="true"/>
<include file="changelog_2.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
The first run ends with an error:
Unexpected error running Liquibase: Data type definition contains unparseable embedded information: ${dbtype.varchar}(20)
So far as I understand the ${dbtype.varchar} comes from my company and in Java code I see a replacement.
My question is for MySQL ${dbtype.varchar} should be replaced with VARCHAR and for SQL Server with nvarchar.
Is there an easy way to tell liquibase to replace this placeholder with MySQL values?
In the liquibase.properties I tell liquibase that it should be done for MySQL.
driver: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
classpath: /home/markus/drivers/mysql-connector-java-5.1.49.jar
EDIT:
I found inside the Liquibase documentation how I can do it with properties from outside.
liquibase --changeLogFile=batch_changelogs.xml update -Ddbtype.bigint=BIGINT -Ddbtype.ubigint='BIGINT UNSIGNED'
It's not exaclty what I'm looking for but at the momement is comfortable to use.
Thanks,
Markus
Finally I found it inside the documentation
In liquibase.properties I can add with the parameter.
parameter.dbtype.bigint=BIGINT
parameter.dbtype.ubigint='BIGINT UNSIGNED'
Solved for MySql. For MSSQL I will generate a new property file and change by exeuction.
I am trying to find the Flyway's beforeEachMigrate equivalent functionality in liquibase. Does liquibase have a way to execute an SQL script before each new migration script is executed?
My current liquibase structure looks like follows.
application.properties file
spring.liquibase.change-log=classpath:db/changelog/changelog-master.yaml
changelog-master.yaml file
databaseChangeLog:
- include:
file: db/changelog/1-initial-schema.sql
- include:
file: db/changelog/2-schema-update.sql
create something like db/changelog/00-init.sql
and put there something like
<changeSet id="1" author="you" runAlways="true">
<sql>...or whatever change</sql>
</changeSet>
note: use runAlways
EDIT: I'm looking into beforeEachMigrate and it executes change before each let's say changeSet. There is no equivalent for that in liquibase so far.
Adding onto what #bilak said, you can also set the parameter using runOrder in addition to runAlways.
Documentation: To always run a changeset before OR after an update - runAlways/runOrder - https://docs.liquibase.com/concepts/changelogs/changelog-formats.html
I'm using liquibase version 3.4
After I execute a liquibase changeset, I see the following entry into the changelog
INSERT INTO DATABASECHANGELOG (ID, AUTHOR, FILENAME, DATEEXECUTED, ORDEREXECUTED, MD5SUM, DESCRIPTION, COMMENTS, EXECTYPE, CONTEXTS, LABELS, LIQUIBASE) VALUES ('1561715333', 'userx', 'C:/TeamCity.BuildAgent/work/CMSLiquibase/src/main/resources/releases/1/core/ddl/JIRA-1000-ADD_COLUMN.xml', SYSTIMESTAMP, 17, '7:762a7c8960445ef94da88c10a81acd79', 'addColumn', 'Adding column', 'EXECUTED', NULL, NULL, '3.4.0');
For filename, liquibase generates the full path "C:/TeamCity.BuildAgent/work/CMSLiquibase/src/main/resources/releases/1/core/ddl/JIRA-1000-ADD_COLUMN.xml" where as I want the relative path "src/main/resources/releases/1/core/ddl/JIRA-1000-ADD_COLUMN.xml"
The liquibase documentation says Filename should be "Path to the changelog. This may be an absolute path or a relative path depending on how the changelog was passed to Liquibase. For best results, it should be a relative path"
But I cannot find any code examples on where this has been configured.
Any idea where I can configure this?
You can use the attribute logicalFilePath in the <databaseChangeLog> tag:
<?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-3.5.xsd"
logicalFilePath="my_changelog.xml"> <<<<HERE
....
</databaseChangeLog>
Unfortunately there is no global setting to do that. You need to take care to do that for every changelog file you have.
Caution
If you change that if you have already run your existing change logs, you need to change the values in the database! Liquibase detects a changeset with the combination of filename, author and id. So if you change the logicalFilePath for something that has already been run, Liquibase will think it's a new change log and will try to run all changesets in the file again.
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
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>