In liquibase I want to execute a particular change set based on the 'context' property value.
In this case I have passed -Dcontext=local (I've checked this values is getting picked properly) through command line and tried to check that property within my changeset by using changeLogPropertyDefined. But It's not working..
Please find below my changeset
<changeSet id="1" author="dm">
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<changeLogPropertyDefined property="context" value="local"/>
</preConditions>
<createTable tableName="accountold">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="version" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
You should add the "link" to the property in the top of your changeset file to reference value is passed from jvm args:
<property name="context" value="${context}"/>
Then you could use your property in precondition and anywhere you want in this changeset.
P.S. Maybe it's will be better to give different name for jvm arg and lb property to avoid ambiguity of interpretation.
I'm making the upgrade of the table that previously was just a join table to the real entity. So, it should have no primary key of ids of the entities it joins, and establish its own id. I tried this update configuration:
<changeSet id="20200429180824-1" author="jhipster">
<dropPrimaryKey columnNames="teacher_id, subject_id" tableName="teacher_subject"/>
<addColumn tableName="teacher_subject" author="jhipster">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="teacher_status" type="varchar(255)" defaultValue="APPROVED">
<constraints nullable="true" />
</column>
<column name="achieved" type="datetime" defaultValueComputed="CURRENT_TIMESTAMP" >
<constraints nullable="true" />
</column>
<column name="active" type="boolean" defaultValue="true">
<constraints nullable="true" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</addColumn>
<dropDefaultValue tableName="teacher_subject" columnName="achieved" columnDataType="datetime"/>
</changeSet>
However, at the migration time I'm getting failure with this exception, despite of my expectation that the column should be just created at the moment and pre-populated with autoIncrement data:
liquibase.exception.DatabaseException: ERROR: column "id" contains null values
However, I have realized the root of the problem here is in forcing "nullable=false". After moving it to the different and later execution of the same changeset, the migration succeed. The final changeset looks like, note separate addNotNullConstraint and primaryKey-only <constraints primaryKey="true"/> here:
<changeSet id="20200429180824-1" author="jhipster">
<dropPrimaryKey columnNames="teacher_id, subject_id" tableName="teacher_subject"/>
<addColumn tableName="teacher_subject" author="jhipster">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="teacher_status" type="varchar(255)" defaultValue="APPROVED">
<constraints nullable="true" />
</column>
<column name="achieved" type="datetime" defaultValueComputed="CURRENT_TIMESTAMP" >
<constraints nullable="true" />
</column>
<column name="active" type="boolean" defaultValue="true">
<constraints nullable="true" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</addColumn>
<addNotNullConstraint catalogName="cat"
columnDataType="bigint"
columnName="id"
constraintName="teacher_subject_id_not_null"
tableName="teacher_subject"
validate="true"/>
<dropDefaultValue tableName="teacher_subject" columnName="achieved" columnDataType="datetime"/>
</changeSet>
The Problem
I recently upgraded Liquibase to 3.6.2 from 3.4.2.
Loading seed data from a CSV into text fields now results in a CLOB resource error. Before it would simply insert the text as a value.
The Setup
I'm using Liquibase to manage migrations of my data.
I have a table with an code and description column. description is of type TEXT.
<changeSet author="" id="create-table-degrees">
<createTable tableName="degrees">
<column name="code"
type="varchar(2)">
<constraints primaryKey="true"/>
</column>
<column name="description"
type="text">
<constraints unique="true"/>
</column>
</createTable>
<rollback>
<dropTable tableName="degrees"/>
</rollback>
</changeSet>
I have seed data in a CSV:
code,description
"D1","MASTERS"
"D2","DOCTORATE"
I load it using loadData:
<changeSet author="" id="seed-degrees">
<loadData file="seeds/degrees.csv"
tableName="degrees" />
</changeSet>
The Error
Unexpected error running Liquibase: CLOB resource not found: MASTERS
The Question
Is there a way to keep Liquibase from interpreting seed values as file paths instead of strings, or do I need to manually define the column types as String in loadData.
e.g. I would like to avoid having to modify the old changeSet to:
<changeSet author="" id="seed-degrees">
<loadData file="seeds/degrees.csv"
tableName="roles">
<column name="description" type="string" />
</loadData>
</changeSet>
The workaround listed in CORE-3287: Anver S December 3, 2018, 3:07 PM
While adding an explicit column type definition as defined in original
stackoverflow post
<column name="description" type="string" />
does the trick - for me it effectively requires to update already
applied changesets which ideally I'd try to avoid.
I m trying to create a relationship between two entities.
Entity Fournisseur(id,code,libelle)
Entity Catalogue (id, fournisseur_code)
I want the relationship between those two entities be between code and fournisseur_code.
I have modified the liquibase xml generated file for entity catalogue from
<changeSet id="20150116113044" author="jhipster">
<createTable tableName="T_CATALOGUE">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="fournisseur_id" type="bigint"/>
<column name="produit_id" type="bigint"/>
<column name="marque_id" type="bigint"/>
<column name="pays_id" type="bigint"/>
<column name="emballage_id" type="bigint"/>
</createTable>
<addForeignKeyConstraint baseColumnNames="fournisseur_code"
baseTableName="T_CATALOGUE"
constraintName="fk_catalogue_fournisseur_id"
referencedColumnNames="id"
referencedTableName="T_FOURNISSEUR"/>
to
<changeSet id="20150116113044" author="jhipster">
<createTable tableName="T_CATALOGUE">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="fournisseur_code" type="varchar(45)"/>
<column name="produit_id" type="bigint"/>
<column name="marque_id" type="bigint"/>
<column name="pays_id" type="bigint"/>
<column name="emballage_id" type="bigint"/>
</createTable>
<addForeignKeyConstraint baseColumnNames="fournisseur_code"
baseTableName="T_CATALOGUE"
constraintName="fk_catalogue_fournisseur_code"
referencedColumnNames="code"
referencedTableName="T_FOURNISSEUR"/>
The table was well generated, but when I m trying to run the getAll function from CatalogueResource, it tells me :
[ERROR] org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Unknown
column 'catalogue0_.fournisseur_id' in 'field list'
I can't figure out why.
If someone knows....
Thank you.
the relation must be connected with the field.
you have to change:
baseColumnNames="fournisseur_code"
to this
baseColumnNames="fournisseur_id"
How do you set the default value of a date column to be "now" in UTC format? I think the answer involves the defaultValueComputed attribute on the column element.
The documentation states:
defaultValueComputed A value that is returned from a function or
procedure call. This attribute will contain the function to call.
What langauge is the function referred to supposed to be written in? Java? Is the function supposed to be the database vendor -specific date function I want to use? Is there any more documentation I can read on this topic?
Maybe this topic in the liquibase forum will help?
I think defaultValueComputed will take a database specific function to express "now". In mySQL it would be CURRENT_TIMESTAMP so it could look like this:
<createTable tableName="D_UserSession">
<column name="ts" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
</createTable>
(Copied from the forum post.)
This should be:
<property name="now" value="now()" dbms="mysql,h2"/>
<property name="now" value="current_timestamp" dbms="postgresql"/>
<property name="now" value="sysdate" dbms="oracle"/>
<property name="now" value="getdate()" dbms="mssql"/>
<changeSet author="me" id="sample_usage_demo">
<addColumn schemaName= "dbo" tableName="demo_table" >
<column name="demo_column" type="datetime" defaultValueDate="${now}">
<constraints nullable="false" />
</column>
</addColumn>
</changeSet>
In MySQL, to use a DATETIME column with fractions of second like DATETIME(6) (microseconds precision), use default value of NOW(6) (caution: CURRENT_TIMESTAMP(6) for some reason produces an error with me using liquibase 3.5.3):
<column name="created_at" type="DATETIME(6)" defaultValueComputed="NOW(6)" >
<constraints nullable="false" />
</column>
Note that the value will be stored internally in UTC, but read using the server's timezone settings (##global.time_zone, ##session.time_zone).
This works with SQlite:
<column name="last_updated_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
Adding '$now' didn't work for me. I am using SQlite as the DB.
This worked for me:
<property name="now" value="UNIX_TIMESTAMP()" dbms="mysql"/>
<column name="ts" type="timestamp" valueDate="${now}"/>
I found it thanks to this answer: https://stackoverflow.com/a/9100388/3107952
You should probably use timestamp with time zone as that will keep the timestamps in UTC as opposed to local server time, which might be problem if you have a multi-region setup.
You can readmore about the timezone part on this Stack Overflow post.
databaseChangeLog:
- changeSet:
id: 007
author: joe
changes:
- addColumn:
tableName: my_table
columns:
- column:
name: created_at
type: timestamp with time zone
- addDefaultValue:
columnName: created_at
defaultValueComputed: now()
tableName: my_table
Due to the fact, that the requested timezone UTC is not mentioned in all of the answers here, I'd like to state another set of solutions for different database vendors.
Especially, the current answers here does not state the correct solution for Oracle.
<changeSet logicalFilePath="my_changeset.xml"
id="1"
author="me"
dbms="mariadb,h2">
<addColumn tableName="MY_TABLE">
<column name="MY_ZONED_DATE_TIME_COLUMN"
type="timestamp(6)"
defaultValueComputed="now()">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
<changeSet logicalFilePath="my_changeset.xml"
id="1"
author="me"
dbms="postgresql">
<addColumn tableName="MY_TABLE">
<column name="MY_ZONED_DATE_TIME_COLUMN"
type="timestamp(6)"
defaultValueComputed="timezone('UTC', now())">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
<changeSet logicalFilePath="my_changeset.xml"
id="1"
author="me"
dbms="oracle">
<addColumn tableName="MY_TABLE">
<column name="MY_ZONED_DATE_TIME_COLUMN"
type="timestamp(6)"
defaultValueComputed="sys_extract_utc(systimestamp)">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
(One may use properties, like showed in Dominika's answer, but we had some really bad experiences with properties in liquibase.)
Summary:
now() is fine for MariaDB, MySql and H2v
now() is not completely fine for H2, I just got a correct result starting the h2 database with UTC like jdbc:h2:mem:./my_database;TIME ZONE=UTC (h2database in version 2.x needed). Then now() is working for sure.
I'm not sure about current_timestamp on PostgreSQL, but timezone('UTC', now()) works. :)
In Oracle, sysdate (mentioned in a few other answers here) is not enough, see as well "How to get UTC value for SYSDATE on Oracle", but sys_extract_utc(systimestamp) does the trick.
I used function the database vendor.
For Oracle it`s a sysdate:
<column name="create_date" type="DATETIME" valueDate="sysdate" defaultValueComputed="sysdate" />
As liquibase is common changelog for any database, to make it generic you should not depend on any specific database like oracle, postegres, mysql instead it should be generic enough to work for any/every database.
Below is how it should be implemented :
<column name="time" type="${type.datetime}" defaultValueComputed="${column.datetime.defaultValue}"/>
This should work for all databases, for oracle, it inserts SYSTIMESTAMP as DATA_DEFAULT.