Liquibase data loading into HSQLDB with a sequence - hsqldb

I'm attempting to load some data into an HSQLDB database using Liquibase 1.9.5. I have a loadData command as follows:
<loadData tableName="LIST_ITEM_TYPE" file="data/global/list_item_type.csv">
<column name="ID" type="NUMERIC" />
<column name="NAME" type="STRING" />
<column name="DESCRIPTION" type="STRING" />
</loadData>
In my CSV data file I'm attempting to set the ID value to the next value from an existing sequence:
id,name,description
next value for SEQ_ITEM_TYPE_ID,Test Name,A test description
However, this doesn't work as it generates the following SQL:
INSERT INTO LIST_ITEM_TYPE (id, description, name) VALUES ('next value for SEQ_ITEM_TYPE_ID', 'A test description', 'Test Name')
This is almost correct, except that the single quotes that Liquibase added around the next value for SEQ_ITEM_TYPE_ID cause HSQLDB to give the following error:
java.sql.SQLException: data exception: invalid character value for cast
If I remove the sinqle quotes and run that SQL manually, it works as expected.
So, my question is, how do I use the Liquibase loadData command pulling data from a CSV file while populating one of the columns from a sequence?

You can achieve this goal by defining a trigger on the target table to use the sequence when the inserted value is a constant that you define. See a related question
Link a sequence with to an identity in hsqldb
Your CSV should probably contain a negative value for the ID column and this should be checked in the trigger WHEN clause.
CREATE TRIGGER trigg BEFORE INSERT ON list_item_type REFERENCING NEW ROW AS newrow FOR EACH ROW WHEN (id < 0) SET newrow.id = NEXT VALUE FOR seq_item_type_id;
Alternatively, insert some sequential numbers in the column using the CSV. After importing the data, use an UPDATE statement to set the values to the seequece. This is practical when the table is not huge. Note the sequential numbers in the insert ensure the insert succeeds if ID is a primary key.
UPDATE list_item_type SET id = NEXT VALUE FOR seq_item_type_id
The third alternative (not using Liquibase) is to create your import file as SQL insert statements rather than CSV. This can be imported into HSQLDB using SQLTool (an HSQLDB utility)

With liquibase 2.0 you may have more options. It may no longer quote the id value if it is defined as number, and/or you can extend the loadData change class to include the SQL.

You can specify that the column is a computed value:
<column name="id" type="computed"/>
this prevents liquibase from putting quotes around the value.

You may be able to use the tag like this:
<modifySql>
<replace
replace="'next value for SEQ_ITEM_TYPE_ID'"
with="next value for SEQ_ITEM_TYPE_ID">
</modifySql>

Solution perfectly worked for me with liquibase 3.2:
<createTable tableName="mytable">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints primaryKey="true" primaryKeyName="mytablePK" />
</column>
...
</createTable>
That definition would create "mytable" table and "mytable_id_seq" sequence as well.
Then, when defining the data in CSV, simply omit the ID column there. Liquibase will do the rest.

Related

Liquibase update values inserting single quotes

I'm trying to upgrade Liquibase from 3.3.1 to 3.10.3. Existing changesets are failing because varchar values being udpated are now inserting additional single quotes. Given the following statement in a changeset:
<update tableName="foo_table">
<column name="foo_id" type="VARCHAR(32)" value="'a'"/>
<where>bar_id REGEXP 'A'</where>
</update>
Liquibase seems to be adding additional single quotes in 3.10.3 so that values in the database are now stored with single quotes. Removing the single quotes from value in the changeset corrects the issue but will change the checksum on many of our changesets. I was wondering if there were any options available that will avoid us from needing to do that.
One option would be to create a new changelog (you can keep your old one, refer to both in order using includeAll in a master changelog). In the new changelog, you can just create your changes in sql.
This would allow you to write the change as sql exactly the way you want it, and liquibase would not have to render the sql based on xml.

How to grab values between xml in SQl statement

When I run a SQL against one of the tables, this is the value i get against column instruction
<GiftMessage>
<Properties>
<Property Type="FONT">50</Property>
<Property Type="SCRIPT">512</Property>
<Property Type="CARD">B</Property>
<Property Type="FORMATOPTION">N</Property>
<Property Type="WRTIE">D</Property>
</Properties>
<Line SeqNo="1"><![CDATA[]]></Line>
<Line SeqNo="2"><![CDATA[]]></Line>
<Line SeqNo="3"><![CDATA[]]></Line>
<Line SeqNo="4"><![CDATA[ ***712020line2***]]></Line>
</GiftMessage>
How do i grab the value "712020line2" alone from the column to show in my output query using select statement.
Apologize for late reply,
I am connected to Oracle database using Oracle sql developer, and below is the query we run.
select instruction_text,order_no from INSTRUCTION_DETAIL where instruction_text like '%712020%';
Purpose
We used to place around 50-70 orders and share it with different team for shipment, updating each order on what needs to be done is tedious task, so we are planning to update that instruction with "what action the shipment team needs to do", so at the end of
day, we just run this query and download it to excel and share. But the thing is the instruction_text column value comes out in an xml format, so looking for a way to fetch only the instruction text, like in above case, '712020line2', from that xml

liquibase subselect - how does one build the XML format?

I would like to use a subselect in a in Liquibase. Does Liquibase support SubSelects other than embedded SQL (i.e. the sql tag) ? If so, can you point me to how to build something like a please?
I assume you mean doing a subselect in an insert or update or create tag.
You cannot use sub-selects in the createTable but you can use the valueComputed tags in and . For example:
<update tableName="person">
<column name="employees" valueComputed="(select count(*) from person where manager=person.id)"/>
</update>
NOTE: If you don't want to drop all the way down to a <sql> tag for commands not handled by the standard XML tags (like subselects in createTable) You can also use to introduce changes and additions to what liquibase can generate from the XML.

How to map small binary objects properly in SQLite/NHibernate combo (wrong type affinity)?

Trying to store property of C#/.NET type byte[] in SQLite. Here is my mapping:
<class name="MyClass" lazy="false" table="MyTable">
<property name="MyProperty" type ="BinaryBlob" access="property" />
</class>
In SQL server it works like a charm even without the explicit type="BinaryBlob" in the mapping. In SQLite I've tried various types' combinations between SQL CREATE TABLE statements and in NHibernate data types, but each time getting either an exception that "the mapping can't be compiled" (because of type incompatibility) or an exception that a cast from the fetched datatype to the mapping type is impossible.
The value of MyProperty in insert statement looks like this: 0x7C87541FD3F3EF5016E12D411900C87A6046A8E8.
Update: continuing to debug System.Data.SQLite.SQLiteDataReader - looks like no matter what SQL type is (tried decimal, blob, unsigned big int) - the type affinity is always text.
What am I doing wrong, please (either technically or in general)? Any suggestion is welcomed.
The reason for text affinity was that the data was imported into a table from CSV (comma-separated values) file. Switching to the SQL file with a proper INSERT statement solved the problem.
Did you look at: How do i store and retrieve a blob from sqlite? There is an article on ayende.com as well here: Lazy loading BLOBS and the like in NHibernate. These links might help push you in the right direction to see what is going on.

How to make Nhibernate generate table with Text field instead of nvarchar(255)

I'm trying to make NHibernate generate my schema/SQL 2008, and using the mapping below it keeps wanting to create an nvarchar(255) column instead of text...any ideas?
<property name="AnnouncementText" column="AnnouncementText" type="StringClob">
<column name="AnnouncementText" sql-type="NTEXT"/>
</property>
Thanks!
The problem is specifying the name of the column twice...once I took it and the length out of the property element it worked perfectly
<property name="AnnouncementText" type="StringClob">
<column name="AnnouncementText" sql-type="text"/>
</property>
I'm used to SQL Server 2005 and the dialect it uses, but I presume you can do something similar. Since nvarchar(n) allows n up to 4000, a value above this will use nvarchar(max).
I presume that SQL Server 2000, which it sounds like you're using, does something similar once you hit the limit. If I read the NHibernate code correctly (NHibernate.Dialect.MsSql2000Dialect..ctor()) you get ntext once you pass 0xFA0 = 4000 characters.
<property name="AnnouncementText" column="AnnouncementText" type="string" length="10000"/>
this won't help at all, but I remember the good old days ;-)...
create table YourTable
(
...
AnnouncementText text null
...
)