Liquibase - generate table names in lowercase - liquibase

I am using Liquibase 3.2.0 to perform an upgrade on an Oracle DB. All the existing table names in my schema are in lowercase
My problem is, when I use Liquibase to run a changeSet, the table names are generated in upper-case.
A typical entry in my changeSet looks as follows:
<changeSet author="me (generated)" id="1403006263048-2">
<createTable tableName="batch_job">
<column name="id" type="number">
<constraints nullable="false" primaryKey="true" primaryKeyName="batch_jobPK"/>
</column>
<column name="version" type="number">
<constraints nullable="false"/>
</column>
<column name="execution_time_stamp" type="timestamp">
<constraints nullable="false"/>
</column>
<column name="reference_region" type="varchar2(5)">
<constraints nullable="false"/>
</column>
<column name="trigger_description" type="varchar2(255)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
However, the resulting table name is: BATCH_JOB
I have tried setting an attribute objectQuotingStrategy="QUOTE_ALL_OBJECTS" in the databaseChangeLog element, with no success.
Is there a way to achieve what I want? I am familiar with the advice offered in Liquibase/PostgreSQL: how to preserve table case correctly?
Any help would be much appreciated. Thanks!

It looks like a bug in how Liquibase is handling case standardization. Could you log an issue at liquibase.jira.com?
For now, the easiset approach would be to use a <modifySql> block to fix the case of the table where it is a problem. Or just fall back on the <sql> tag.

Thanks Nathan, lowercase issue is resolved by using <modifysql> as
<modifySql>
<replace replace="filter" with="FILTER"/>
</modifySql>

Related

Dropping a table with a loadUpdateData changeset in Liquibase

The Setup
I am using Liquibase to manage my project's migrations.
I have several tables with several sets of seed data.
Each seeded table has a changeset to create the table, followed by a changeset to load the seed data. The seeds are being loaded using loadUpdateData. This is a smart method that will load seed data from a CSV, if the CSV content is edited it will make the appropriate edits directly.
The seed ChangeSets are in a separate ChangeLog that is always run after the core ChangeLog. This way the seed files can always reflect the correct table structure.
The Problem
I need to drop a table that has seed data. The loadUpdateData command errors because the table no longer exists by the time it is run.
The Code
Create Table ChangeSet
<changeSet author="" id="create-table-help-items">
<createTable tableName="help_items">
<column name="help_item_id"
type="bigint">
<constraints primaryKey="true"/>
</column>
<column name="title"
type="text" />
<column name="description"
type="text" />
</createTable>
<rollback>
<dropTable tableName="help_items"/>
</rollback>
</changeSet>
Seed ChangeSet
<changeSet author="" id="seed-help-items" runOnChange="true">
<loadUpdateData file="db/seeds/help_items.csv"
primaryKey="help_items_id"
tableName="help_items" />
</changeSet>
Drop Table ChangeSet
<changeSet author="" id="remove-table-help-items">
<dropTable tableName="help_items"/>
<rollback changeSetId="create-table-help-items" changeSetAuthor=""/>
</changeSet>
The Questions
Given that it is bad practice to ever delete changesets from a changelog.
What is the right way to create seed migrations so that they don't break when the table is deleted?
Do I need to keep the seed files for tables that have been dropped?
I had the same problem and now i solved it, it works already by me.
The point is that you should set the Rollback in "Drop Table ChangeSet" correctly.
So by droping a table, you should already prepare for the situation of rollback.
<changeSet author="" id="remove-table-help-items">
<dropTable tableName="help_items"/>
<rollback>
<createTable tableName="help_items"/>
</rollback>
</changeSet>
I solved this issue by setting runAlways: false for loadUpdateData changeset. So, it doesn't fail when the table is dropped.

Adding 'CONSTRAINT ensure_json CHECK (po_document IS JSON))' in liquibase

I want to add check constraint to BLOB type column which stores JSON data, in CREATE Table script in liquibase(version 3.3.5, database -Oracle 12C). but it does not compile. Can anyone please explain what is the right syntax to add constraint which ensures only JSON type data would be inserted. I followed this question
Plain sql : CONSTRAINT ensure_json CHECK (po_document IS JSON))
But not sure what is liquibase equivalent for this.
PostgreSQL Check Constraint in Liquibase
<changeSet id="Change_id" author="xqz">
<createTable tableName="table_name">
<column name="pkey" type="int">
<constraints primaryKey="true"/>
</column>
<column name="table2_pkey" type="int">
<constraints nullable="false"/>
</column>
<column name="name" type="varchar(100)">
<constraints nullable="false"/>
</column>
<column name="filters" type="BLOB">
<constraints checkConstraint="ensure_json CHECK (filters IS JSON)" />
</column>
</createTable>
</changeSet>
If I add constraint to filters column, build fails, If I remove it, build is successful. What am I doing wrong. I could not find syntax for it in liquibase docs.
You cannot define check constraints in liquibase, for aditional information see this forum entry.
You'll have to use an <sql> tag like
<sql dbms=oracle>
CREATE TABLE table_name (
pkey integer PRIMARY KEY,
table2_pkey integer NOT NULL,
name varchar(100) NOT NULL,
flter blob CONSTRAINT ensure_json CHECK (filters IS JSON)
)
</sql>
Should work just the same, except that you have to add your own <rollback> tag.

how to execute only specific changesets in liquibase which are unread?

I have added some new changesets in an existing changelog file and want to execute only 2 among the new inserted ones. When I give the update command in liquibase it updates all the unread changesets and updates the database. But I want to execute only 2 among these newly inserted changesets in the changelog file. Is there any way of doing this in liquibase? If yes how is it possible?
One way you could do this is to mark the relevant changesets with a label, and then use that label in your liquibase update command.
This blog post on labels describes their use.
Here is an example that matches what you described in your comment below.
changelog
<?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="steve" labels="labelOne">
<createTable tableName="tableOne">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
<changeSet id="2" author="steve" labels="labelTwo">
<comment>Creating table "tableTwo"</comment>
<createTable tableName="tableTwo">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
<changeSet id="3" author="steve" labels="labelThree">
<comment>Creating table "tableThree"</comment>
<createTable tableName="tableThree">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false" />
</column>
</createTable>
</changeSet>
</databaseChangeLog>
command execution
If you wanted to update and only create table one, you would use this command (if you are using the command line, and assuming that you have a liquibase.properties file that specifies all the connection information, etc.)
liquibase --changeLogFile=changelog.xml --labels=labelOne update
If you wanted to apply two changesets, you would use a command like this:
liquibase --changeLogFile=changelog.xml --labels="labelOne and labelTwo" update

How to insert using a sequence with Liquibase

I would like to do a liquibase insert with the primary key being auto generated from the sequence defined in the database. The target database is HSQLDB.
It works to do an insert specifying a value for the primary key
<insert ...>
<column name="TAG_ID" valueNumeric="2"/>
I found this (admittedly older) conversation about it but the issue is still the same. The suggested fix doesn't work for HSQLDB.
Looking at the docs I've tried some things like
<column name="TAG_ID" defaultValueSequenceNext="TAG_ID_SEQ" />
<column name="TAG_ID" defaultValueSequenceNext="TAG_ID_SEQ.NEXTVAL" />
<column name="TAG_ID" valueComputed="TAG_ID_SEQ.NEXTVAL" />
<column name="TAG_ID" autoIncrement="true" />
but none of those put anything in the key when I do the insert (the insert fails on a null primary key).
How does one accomplish this?
HSQLDB has a setting to use Oracle syntax. You can set HSQLDB to use oracle syntax like so:
<changeSet ...
<sql dbms="hsqldb" >SET DATABASE SQL SYNTAX ORA TRUE</sql>
</changeSet>
After that, it works to do the insert like this:
<insert ...
<column name="TAG_ID" valueComputed="TAG_ID_SEQ.NEXTVAL"/>

How to execute an update via SQLQuery in Hibernate

I need to update a joined sub-class. Since Hibernate doesn't allow to update joined sub-classes in hql or named-query I want to do it via SQL. I also can't use a sql named-query because updates via named-query are not supported in Hibernate.
So I decided to use a SQLQuery. But Hibernate complaints about not calling addScalar():
org.hibernate.QueryException: addEntity() or addScalar() must be called on a sql query before executing the query.
Are updates returning the number of rows affected and how is named that column?
Are there any other ways to do an update on a joined sub-class in hibernate?
Here is a brief example of what i'm trying to do:
<hibernate-mapping>
<class name="example.NiceClass" table="NICE_CLASS">
<meta attribute="class-code"></meta>
<id name="id" type="java.lang.Long">
<column name="NICE_CLASS_ID" precision="8" />
<generator class="sequence">
<param name="sequence">NICE_CLASS_SEQ</param>
</generator>
</id>
</class>
</hibernate-mapping>
<hibernate-mapping package="example">
<joined-subclass name="SubJoinedClass" table="SUB_JOINED_CLASS"
extends="NiceClass">
<key column="NICE_CLASS_ID" foreign-key="NICE_JOINED_ID_FK"/>
<property name="name" type="string" not-null="false">
<column name="NAME" >
<comment>name</comment>
</column>
</property>
</joined-subclass>
</hibernate-mapping>
Thanks in advance!
So I want to do a:
update SubJoinedClass set name = 'newName'
How do you execute the update query ? What method do you call to execute it ? Do you call 'ExecuteUpdate' ?
And why do you think that you cannot execute an update query on a subclass using HQL ? AFAIK, it is possible.