Liquibase generateChangeLog not including column length (MySQL) - mysql

I'm using Liquibase's generateChangeLog command as follows:
liquibase --driver=com.mysql.jdbc.Driver \
--classpath=$HOME/.m2/repository/mysql/mysql-connector-java/5.1.26/mysql-connector-java-5.1.26.jar \
--changeLogFile=./db.changelog.xml \
--url="jdbc:mysql://localhost:3306/db" \
generateChangeLog
Which outputs XML change log without column length definitions for all columns.
Example:
<changeSet author="purecharger (generated)" id="1461081110463-2">
<createTable tableName="account">
<column name="id" type="BIGINT">
<constraints nullable="false"/>
</column>
...
</createTable>
</changeSet>
Column Definition (snippet):
Create Table: CREATE TABLE `account` (
`id` bigint(20) NOT NULL,
...
Why doesn't the changelog include length, like so?
<column name="id" type="BIGINT(20)">
<constraints nullable="false"/>
</column>

In MySQL, BIGINT specifies 8 bytes of space, which is enough for integers from -9223372036854775808 to 9223372036854775807. BIGINT(20) doesn't really mean anything. MySQL is being generous by accepting it.
Full details at this MySQL page: https://dev.mysql.com/doc/refman/5.5/en/integer-types.html

Related

How to set column default value to today's date in SQL using XML

I want to add a column to one of my SQL schema's tables.
I have tried the following:
<property name="now" value="now()" dbms="mysql"/>
<changeSet author="Trey Collier" id="SCHEJ-376">
<addColumn tableName="schedule">
<column name="dateLastPublished" type="DATETIME" defaultValueDate="${now}">
<constraints nullable="false" />
</column>
</addColumn>
</changeSet>
However, this inserts the date in the format YYYY-MM-DD hh:mmm:ss, but I only want the YYYY-MM-DD part of it. How can I change my current XML code to make this happen? Thanks
You should change defaultValueDate="${now}" with defaultValueDate="(DATE(CURRENT_TIMESTAMP))" and type="DATETIME" with type="DATE"

Liquibase inserts wrong default date value into MySql

I have changelog:
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.0.xsd">
<changeSet id="10" author="vaa25">
<createTable tableName="test" schemaName="liquibase">
<column name="id" type="INT" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="created_at" type="DATETIME(3)" defaultValueDate="CURRENT_TIMESTAMP(3)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
Result of execution:
liquibase.exception.DatabaseException: Invalid default value for 'created_at' [Failed SQL: (1067) CREATE TABLE liquibase.test (id INT AUTO_INCREMENT NOT NULL, created_at datetime(3) DEFAULT NOW() NOT NULL, CONSTRAINT PK_TEST PRIMARY KEY (id))]
Cause: liquibase substitutes NOW() instead NOW(3).
Yes, of course I can apply 'sql' tag with correct native sql script, but anyway seems it is liquibase bug. Liquibase 4.0.0 and Mysql 8.0.15 used.
This is more bug report then question.

Liquibase - Add defaultValueComputed as CURRENT_TIMESTAMP to timestamp column

I am using liquibase 3.5.3 to run liquibase update command on MySql 5.5. I have below changeSet to create a table which has a column as Created_Time that should have a default value as CURRENT_TIMESTAMP.
<changeSet author="authorName" id="AutoGeneratedId">
<createTable tableName="aTable">
<column autoIncrement="true" name="Id" type="INT">
<constraints primaryKey="true"/>
</column>
<column name="Code" type="VARCHAR(45)"/>
<column defaultValueComputed="CURRENT_TIMESTAMP" name="Created_Time" type="TIMESTAMP(19)"/>
</createTable>
</changeSet>
While firing liquibase command it throws an exception as
Unexpected error running Liquibase: Invalid default value for 'Created_Time' [Failed SQL: CREATE TABLE aTable (Id INT AUTO_INCREMENT NOT NULL, Code VARCHAR(45) NULL, Created_Time TIMESTAMP(19) DEFAULT NOW() NULL, CONSTRAINT PK_ATABLE PRIMARY KEY (Id))]
Liquibase is converting CURRENT_TIMESTAMP into NOW() that might be causing this issue.
Can some please provide me any solution or alternative to this issue?
Add type as 'TIMESTAMP' as following
<column defaultValueComputed="CURRENT_TIMESTAMP" name="Created_Time" type="TIMESTAMP"/>
This is a weird scenario causes by how liquibase handles DateTime defaultValueComputed or defaultValueDate.
In short anything that starts with current_timestamp or the default function on your target engine to get the current timestamp will replace *the whole string* by only the default function call ignoring anything else you put.
We ended up with something like this:
<column name="created_at" type="datetime"
defaultValueComputed="NOW()">
<constraints nullable="false" />
</column>
<column name="updated_at" type="datetime"
defaultValueComputed="NOW() ON UPDATE NOW()">
<constraints nullable="false" />
</column>
LiquibaseDataType helper function

Liquibase modifyDataType fails on Mysql

I don't seem to be able to execute a type modification on a Mysql 5.7.10 instance (it works with H2 though).
Here are the changeset steps that are involved with the regarded field:
Creation:
<column name="last_modify_time" type="bigint">
<constraints nullable="false" />
</column>
Modification:
<modifyDataType tableName="USER" columnName="last_modify_time" newDataType="timestamp" />
the error msg in Mysql is
Invalid default value for 'last_modify_time' [Failed SQL: ALTER TABLE USER MODIFY last_modify_time timestamp]
Manually modifying the the request to the following works:
ALTER TABLE USER MODIFY last_modify_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
I don't really understand why Mysql needs the default value. Maybe it's an edge case with the version 5.7.10 (using the default configuration options).
In any case Liquibase should be able to handle it.
I've tried to add/remove default value prior to the modifyDataType, without success.
when you are modifying type of a column using liquibase which is non nullable ... you have to first make it nullable and then modify it use safe modify
It turns out that an exactly identical modification on a field named create_time, placed right before, didn't cause any problem. Swapping the two changsets order did solve the problem.
<changeSet id="11" author="author">
<comment>rename last_modify_time to last_modified_date and change type to timestamp</comment>
<modifyDataType tableName="USER" columnName="last_modify_time" newDataType="timestamp" />
<renameColumn tableName="USER" oldColumnName="last_modify_time" newColumnName="last_modified_date" columnDataType="timestamp" />
</changeSet>
<changeSet id="12" author="author">
<comment>rename create_time to created_date and change type to timestamp</comment>
<modifyDataType tableName="USER" columnName="create_time" newDataType="timestamp" />
<renameColumn tableName="USER" oldColumnName="create_time" newColumnName="created_date" columnDataType="timestamp"/>
</changeSet>
I still can't explain what happend, I'm happy enough to get it working. If someone wants to reproduce the error I'd be happy to help.

Boolean insertion without quotes - Liquibase over MySQL

I need to insert new record on this users table with Liquibase. It works well on PostgreSQL, but when it comes to MySQL the SQL output has quotes for the boolean field (u_administrator). Like this:
INSERT INTO users (u_name, ..., u_administrator) VALUES ('Administrator',..., '1')
<changeSet author="jmartins" id="AdminInsertion">
<insert tableName="users" dbms="postgresql">
<column name="u_name" value="Administrator"/>
...
<column name="u_administrator" value="true"/>
</insert>
<insert tableName="users" dbms="mysql">
<column name="u_name" value="Administrator"/>
...
<column name="u_administrator" value="1"/>
</insert>
</changeSet>
So I can I force liquibase to output "u_administrator" without quotes so it can insert correctly on MySQL. Do I need to go for a < sql> custom command?
Thanks anyway.
Use valueBoolean instead of value to tell liquibase it needs to use the database-specific value for a boolean value.