I'd like to use JDBC to create tables in a database agnostic way. I'm pretty sure that Liquibase has solved this problem since it can take a generic createTable XML changeSet element and convert it into a database specific SQL DDL statement.
Can someone please tell me which liquibase classes / utililities are involved in converting a generic createTable changeSet into a database specific create table SQL script?. Sample usage (ie a test case) would be great.
Please note that I do not wish to invoke the entire liquibase pipeline. In particular I do NOT want the databasechangelog table.
I'd recommend reading the liquibase unit tests.
Related
I would like to run a SQL precondition checking for each changeSet in my SQL changeLogFile. It is actually a precondition on the changeLog itself
Here is an extract of it :
--liquibase formatted sql
--preconditions onFail:HALT onError:HALT
--precondition-sql-check expectedResult:"1.0" SELECT VERSION FROM VERSION_TABLE;
--changeset bob:1 failOnError:true dbms:oracle
ALTER INDEX XXX RENAME TO YYY;
--rollback YYY RENAME TO XXX;
Even if the precondition is actually not respected, liquibase still run all the changeset.
Does somebody knows if it is an error from my side or if liquibase does not allow preconditions on entire changeLog for SQL changeLog file ?
Thanks in advance !
If you go through the documentation, then its stated that we can only apply pre-conditions on a specific change set. Also, only the SQL Check precondition is supported.
Liquibase doc for sql changelog files - https://www.liquibase.org/documentation/sql_format.html
One thing you could do is have a top-level master changelog in XML/YAML/JSON format and then use <include> or <includeAll> elements to include your liquibase formatted sql changelogs. If you do that, then you can have changelog-level preconditions.
Liquibase main purpose is for detecting DDL (schema) changes.
Can it be used to deploy DML (data) changes as well ?
I mean is it possible to write changesets for doing inserts with data?
Yes, it's possible with liquibase.
Just use <update> tag for data update.
Or use <sql> tag for data insert or for whatever SQL queries you actually want.
I wanted to change the data type of one field from string to date. So i dropped the table in db. Then modified the liquibase file and ran the application. now it complains with the following message.
liquibase.exception.ValidationFailedException: Validation Failed:
So after that I reverted the liquibase file changes and ran the application. This time no error but it is not creating the table.
Please help me how to solve this issue.
I assume the failed validation was an error about checksums. This happens when you modify a changeset which was already executed and try to execute it again.
Liquibase keeps all executed changesets in a table called databasechangelog, so it can find out which changesets can be skipped during execution.
To execute a changeset again, delete the corresponding from this table before, and run Liquibase again.
When using Liquibase, you shouldn't (in general) modify the database outside of Liquibase - the main exception being if you are a developer working on your own private development database. If you are in that state (working on your own private database), then when you modify the database outside of Liquibase (i.e. dropping a table) you will also need to delete the row in the DATABASECHANGELOG table that corresponds to the table create statement so that when you re-run liquibase update it will re-create the table.
Liquibase ask for fully defined schema Name, for example for the indexExists tag. But what if want to run a changeset on multiple schema. Is there a way to indicate running on the current schema, or to dynamically set it when running an update ?
My Bad, that schemaName is not a required attribute for createIndex.
In our case liquibase is used to update databses for existing installation. New installations are already up to date.
Assuming we have got a new installation. Starting the application will force to execute liquibase changesets (e.g. change type of a column) but as I mentioned before there is nothing to update as the column already was created with the correct type.
Does liquibase recognize that the table column is already up to date or does it try to execute the changeset as there is no entry within the databasechangelog table for it?
Liquibase uses an alternative approach that avoids a need to analyze the target database's data dictionary. This makes DB operations simpler and more cross platform.
A special table "DATABASECHANGELOG" keeps a record of the changesets applied to the target database instance. This table also contains a checksum (calculated at runtime) to determine if changsets are altered between runs of liquibase.
So if you altered the type of a table column, liquibase can detect this and can throw an error, when run against an existing database. (Obviously, on a new DB, the table would be created as expected).
Finally, the changeset documentation describes two optional attributes ("runAlways" and "runOnChange") which could tell lqiuibase to reapply a changeset more than once to a database. There is also a "clearCheckSums" command that can be used to reset the checksums on an existing database. Obviously you need to know what you're doing when using such an option :-)
Liquibase will not recognize anything automatically.
But you can use <preConditions/> in your changeSet to check if your changeSet must be applied or not.