How to add condition to changeSet - liquibase

I created database ChangeLog for liquibase and I have "CREATE TABLE" query.
I want to add condition to column "STATUS".
<?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">
<changeSet id="1" author="xxx">
<comment>Create Asset table</comment>
<sql>
CREATE TABLE `TASK`(
`TASK_ID` bigint(20) NOT NULL,
`STATUS` VARCHAR(10), //(where status not equal to "pending")
`FILE_ID` varchar(100),
PRIMARY KEY (`DOC_ID`)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
</sql>
</changeSet>
</databaseChangeLog>

If you want to update the columns datatype depending on certain conditions, you can use <preConditions> with <sqlCheck>, and then use <modifyDataType>.
So supposing that there's already a table with name TASK and it contains a column named STATUS, you can modify it's datatype as such:
<changeSet id="1" author="xxx">
<comment>Update Asset table</comment>
<preConditions onFail="MARK_RAN">
<and>
<columnExists tableName="TASK" columnName="STATUS"/>
<sqlCheck expectedResult="0"> SELECT COUNT(*) FROM TASK WHERE STATUS = "pending";</sqlCheck>
</and>
</preConditions>
<modifyDataType tableName="TASK" columnName="STATUS" newDataType="VARCHAR(10)"/>
</changeSet>
Or perhaps you'd like another onFail-behaviour. Check out this link
HALT - Immediately halt execution of entire change log [default]
CONTINUE - Skip over change set. Execution of change set will be
attempted again on the next update. Continue with change log.
MARK_RAN - Skip over change set, but mark it as ran. Continue with
change log
WARN - Output warning and continue executing change set as normal.

Related

Two conditions in where tag of Liquibase

I want to add two conditions in where tag of liquibase and exception is thrown:
Reason: liquibase.exception.DatabaseException: Unknown column 'uid' in 'where clause' [Failed SQL: UPDATE kw.media_file SET created = '1586352959' WHERE id=1 AND uid='admin']
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
Here is the changeLog:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<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"
logicalFilePath="src/main/resources/db/update.xml">
<changeSet author="author" id="20200409-update">
<update tableName="media_file">
<column name="last_modified" type="int(11)" value="1586438425"/>
<where>id=1 AND uid='admin'</where>
</update>
</changeSet>
Equivalent sql statement is here:
update person set created = 1586352959 where id = 2 and uid='admin';
When I run the SQL statement, the column is updated but no luck with liquibase.
As stated in the comment - the error and the changeSet you've provided don't match each other.
The error is that column uid is not found in table media_file
Your changeSet is synthetically correct, and you can provide multiple conditions in one <where> tag.
Based on the SQL statement you've provided
update person set created = 1586352959 where id = 2 and uid='admin';
So I can assume the changeSet you're looking for may look something like:
<changeSet author="foo" id="bar">
<update tableName="person">
<column name="created" type="int(11)" value="1586438425"/>
<where>id = 2 AND uid = 'admin'</where>
</update>
</changeSet>

Liquibase sql generated error with column comments?

When I add a new column comment , liquibase give me an error sql. How can I fix it ?
xml like :
<databaseChangeLog xxxxxxxx>
<changeSet author="root (generated)" id="1574189348049-1">
<setColumnRemarks columnName="nickname" remarks="nickname" tableName="t_user"/>
</changeSet>
</databaseChangeLog>
sql like :
ALTER TABLE testdb.t_user COMMENT = 'nickname';

Set initial value in liquibase with postgresql database

I have a table and i need that it's ID start in 1000000.
I have this code set for liquibase:
<column name="id" type="bigint" autoIncrement="true" startWith="1000000">
<constraints primaryKey="true" nullable="false"/>
</column>
But it does not work in postgres, the generated sequence generator starts with 1.
Does anyone has any idea on this? How can i enable a table to start from a value in liquibase that works with postgresql?
Thanks in advance!
just alterSequence won't help:
<alterSequence
minValue="1000000"
sequenceName="t1_id_seq"/>
Unexpected error running Liquibase: ERROR: START value (1) cannot be
less than M INVALUE (1000000) [Failed SQL: ALTER SEQUENCE
public.t1_id_seq MINVALUE 1000000]
and according to docs you can't start sequence with alterSequence, so you have to createSequence with
<createSequence
sequenceName="seq_id"
startValue="1000000"/>
and then "assign" it as default value to your bigint column
<sql dbms="postgresql" endDelimiter=";\n" splitStatements="true"
stripComments="true">ALTER TABLE t1 ALTER COLUMN id SET DEFAULT nextval('seq_id');
</sql>
or initially use bigserial and sql to restart sequence:
<changeSet author="Vao" id="1">
<createTable tableName="t2">
<column name="id" type="bigserial">
<constraints primaryKey="true" primaryKeyName="t2_pkey"/>
</column>
</createTable>
</changeSet>
<changeSet author="Vao" id="2">
<sql dbms="postgresql" endDelimiter=";">ALTER SEQUENCE t2_id_seq restart with 1000;
</sql>
</changeSet>
Unfortunately startWith don't seems to work for postgres db.
You can use (with yaml configuration) :
- changeSet:
id: add-auto-increment-postgres
author: me
dbms: postgresql
changes:
- createSequence:
sequenceName: my_sequence
startValue: 1000
- addDefaultValue:
columnName: id
defaultValueSequenceNext: my_sequence
tableName: my_table
Thx! Drop and create new - helps
dropSequence
createSequence

How do I get liquibase to skip table creation if it already exists with liquibase formatted sql?

This is what I have
--preconditions onFail:CONTINUE
--preconditions not tableExists tableName:QRTZ_CALENDARS schemaName:dbo
CREATE TABLE dbo.QRTZ_CALENDARS (
SCHED_NAME VARCHAR (120) NOT NULL ,
CALENDAR_NAME VARCHAR (200) NOT NULL ,
CALENDAR IMAGE NOT NULL
)
GO
Background. I'm using liquibase to setup a h2 database for test cases in java.
Add a pre-Condition to your changeset for example:
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="Table_name"/>
</not>
</preConditions>
<createTable tableName="Table_name" >
<column name="column1" type="NUMBER(20,0)"/>
</createTable>
At the moment "formatted SQL" changelogs only support the "SQL check" precondition.
Example:
--preconditions onFail:HALT onError:HALT
--precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM my_table
Info source (and updates): https://docs.liquibase.com/concepts/changelogs/preconditions.html
If more complicated preconditions are required -- one could try moving to a non-SQL Liquibase format, i.e. XML or JSON

Update type of a column in liquibase

I want to update the type of a column named "password". At the moment it has type NVARCHAR(40) and I want it to be of type NVARCHAR(64). This is what I did:
<changeSet id="1 - change password length" author="chris311">
<update tableName="tablename">
<column name="password" type="NVARCHAR(64)"/>
</update>
</changeSet>
What else is there to do? Because this obviously does not change anything in the DB.
You're using the wrong refactoring operation. Try modifyDataType
<changeSet id="increase-password-length" author="martin">
<modifyDataType tableName="tablename" columnName="password" newDataType="NVARCHAR(64)"/>
</changeSet>
You can check out http://www.liquibase.org/documentation/changes/modify_data_type.html for more documentation
Or you can do by using sql tag:
<changeSet author="liquibase-sql" id="example-sql" context="migrate">
<sql dbms="mysql">
ALTER TABLE tablename MODIFY COLUMN password NVARCHAR(64)
</sql>
</changeSet>