Force Liquibase to map Blob to BYTEA on PostgreSQL - postgresql

How to tell Liquibase to map BLOB datatype to BYTEA on PostgreSQL?
It seems that Hibernate people has taken over and adapted the tool to their needs: https://liquibase.jira.com/browse/CORE-1863 , however, EclipseLink don't support oid's and the bug seems to be still open: https://bugs.eclipse.org/bugs/show_bug.cgi?id=337467
I need to use EclipseLink, and I need to use blobs with PostgreSQL. I'd like to use Liquibase, is it possible to make those things work together?

You have two options.
If you only need this for Postgres and don't plan to support other DBMS, simply use bytea as the column type.
Any data type that is not listed as one of the "generic" types in the description of the column tag will be passed "as-is" to the database, e.g.
<createTable tableName="foo">
<column name="id" type="integer"/>
<column name="picture" type="bytea"/>
</createTable>
If you want to support different DBMS, you can define a property depending on the DBMS:
<property name="blob_type" value="bytea" dbms="postgresql"/>
<property name="blob_type" value="blob" dbms="oracle"/>
then later
<createTable tableName="foo">
<column name="id" type="integer"/>
<column name="picture" type="${blob_type}"/>
</createTable>

Related

Liquibase: added autoIncrement column into a table with data already present

Hi guys I have some doubt about Liquibase
I created a table (PostgreSQL) with a classical changeset
<changeSet id="create_table">
<createTable tableName="table" schemaName="schema">
<column name="name" type="varchar">
<constraints nullable="false"/>
</column>
<column name="surname" type="varchar">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
I've already added some data to this table.
I want to add a new column 'id' and make it as a primary key as an autoincrement column.
How can I do that?
Because if I try to add a changeset like this:
<changeSet id="added_pk">
<addColumn tableName="table"
schemaName="schema">
<column name="id" type="bigint">
<constraints unique="true" nullable="false" uniqueConstraintName="PK_TABLE_ID"/>
</column>
</addColumn>
<addAutoIncrement columnDataType="bigint"
columnName="id"
tableName="table"
schemaName="schema"
incrementBy="1" startWith="1"/>
</changeSet>
I obtain error when I run the script: "column "id" of relation "table" contains null values".
It depends of the already existing values. How could I manage this situation? (I prefer to avoid to truncate all the data before add the new column)
Thanks a lot!
Regards
Rename the current table in the DB. Delete the liquibase changelogs. Rerun the liquibase file including the new id field (you can combine the two changeSets, this way you also get to decide the position of the id field). After the new table has been created you can transfer the data from the old table into the new table. This way the data from the old table will automatically receive ids. Delete the old table at the end.

Liquibase database autocomplete using Eclipse

Is there a way to get autocomplete for columns and tables from my database in a changelog file ?
<changeSet id="001" author="test">
<insert tableName="person">
<column name="id" valueComputed="seqPerson.NEXTVAL" />
<column name="myName" value="test" />
</insert>
<rollback>
DELETE FROM person WHERE myName='test';
</rollback>
</changeSet>
In this example I would like to have autocomplete for person, id, myName and seqPerson (and the Rollback tag...).
Note that I already have the LiquiBase tags autocompletion working from the xsd.
No, this is not currently possible. You might look at Datical DB - it has a changeset wizard that provides this sort of functionality.
Disclaimer - I work for Datical.

liquibase:updateSQL does not create table schema prefix

I run liquibase:updateSQL with the following parameters on postgres:
changelogSchemaName online
defaultCatalogName online
defaultSchemaName online
It generates SQL like CREATE TABLE product but what I would expect is CREATE TABLE online.product
With the generated SQL the users search_path is used so I need to modify my DB before I can use liquibase:update
any Ideas how to fix that?
Have you used the catalogName attribute as described in the documentation?
For example:
<changeSet author="liquibase-docs" id="createTable-example">
<createTable catalogName="online" tableName="product"
<column name="x" type="varchar(255)"/>
<column name="y" type="varchar(255)"/>
</createTable>
</changeSet>
Use the outputDefaultCatalog=true or outputDefaultSchema=true maven parameters. That will force the generated SQL to include the default schema even if it is not specified in the changeSet.

Liquibase/PostgreSQL: how to preserve table case correctly?

I'm using Liquibase 3.1.1 to create tables in PostgreSQL 9.1. For example:
<changeSet id="1" author="bob">
<createTable tableName="BATCHES">
<!-- .. -- >
</createTable>
</changeSet>
However, the table gets created with a lowercase name:
# select * from "BATCHES";
ERROR: relation "BATCHES" does not exist
Is there any way to have Liquibase generate DDL that preserves the case of the table (and column etc) names that I specify in the change log?
You can use the objectQuotingStrategy="QUOTE_ALL_OBJECTS" attribute on your changeSet attribute or on the databaseChangeLog root element to override the default logic of "only quote objects that have to be"

enum data type for liquibase

I'm currently working on a liquibase.xml file to create table table_a. One of my fields is <column name="state" type="ENUM('yes','no')">
I'm using postgresql as my DBMS. is there anything like enum data type?
I've read in this like http://wiki.postgresql.org/wiki/Enum
that postgresql doesn't have such data type. CREATE TYPE function is used to create this data type. I still don't know how to make it in liquibase though.
Any suggestions?
Well of course PostgreSQL has an enum type (which is clearly documented in the link you have shown and the manual).
I don't think Liquibase "natively" supports enums for PostgreSQL, but you should be able to achieve it with a custom SQL:
<changeSet id="1" author="Arthur">
<sql>CREATE TYPE my_state AS ENUM ('yes','no')</sql>
<table name="foo">
<column name="state" type="my_state"/>
</table>
</changeSet>
For a simple yes/no column, I'd actually use the boolean type instead of an enum
An alternative to creating a new type would be a simple CHECK constraint on a varchar(3) column:
<changeSet id="1" author="X">
<table name="t">
<column name="c" type="varchar(3)"/>
</table>
<sql>ALTER TABLE t ADD CONSTRAINT check_yes_no CHECK (c = 'yes' OR c = 'no')</sql>
</changeSet>
That might play better with the client side, or not. I think boolean (as suggested by a_horse_with_no_name) would be a better call for this specific case: saying exactly what you mean usually works out better than the alternatives.