LiquiBase: <preConditions>
There are three main reasons to use preconditions:
- Document what assumptions the writers of the changelog had when creating it.
- Enforce that those assumptions are not violated by users running the changelog
- Specify them on changeSet tags as a data check before performing an unrecoverable change such as dropTable
Sample With Preconditions
<?xml version="1.0" encoding="UTF-8"?> <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.7" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.7 http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.7.xsd"> <preConditions> <dbms type="oracle" /> <runningAs username="SYSTEM" /> </preConditions> <changeSet id="1" author="bob"> <preConditions> <sqlCheck expectedResult="0">select count(*) from oldtable</sqlCheck> <preConditions> <dropTable tableName="oldtable"/> </changeSet> </databaseChangeLog>
The above changelog will only run if the database executed against is Oracle and the database user executing the script is “SYSTEM”
Available Preconditions
<dbms>
Specifies the expected database system. Set the “type” attribute to “mysql”,”postgresql”,”oracle”, “mssql”, “hsqldb” or “derby”
<runningAs>
Specifies the expected user information. Set the “username” attribute to the username of the database user
<sqlCheck>
Executes an SQL string and checks the returned value.
The SQL statement must return a single value in a single row. Set the “expectedResult” attribute to the value that you want the precondition to pass for.
<sqlCheck expectedResult="1">SELECT COUNT(1) FROM pg_tables WHERE TABLENAME = 'myRequiredTable'</sqlCheck>
<customPrecondition>
To create your own custom precondition, simply create a class that implements the liquibase.precondition.CustomPrecondition interface and reference it with the className parameter on the customPrecondition tag. Since 1.7
AND/OR/NOT Logic
Conditional logic can be applied to preconditions using nestable <and>, <or> and <not> tags. If no conditional tags are specified, it defaults to AND.
For example:
<preConditions> <dbms type="oracle" /> <runningAs username="SYSTEM" /> </preConditions>
Will require running on Oracle AND with the SYSTEM user
<preConditions> <dbms type="oracle" /> <dbms type="mssql" /> </preConditions>
Will require running on Oracle AND MS-SQL, which will always be false, unless a huge and unexpected merger takes place.
<preConditions> <or> <dbms type="oracle" /> <dbms type="mssql" /> </or> </preConditions>
Will require running on Oracle OR MS-SQL which makes more sense than the above example.
<preConditions> <or> <and> <dbms type="oracle" /> <runningAs username="SYSTEM" /> </and> <and> <dbms type="mssql" /> <runningAs username="sa" /> </and> </or> </preConditions>
Will require running as SYSTEM if executing against an Oracle database or running as SA if running against a MS-SQL database.
Implementation Notes
Preconditions are checked at the beginning of the execution of a particular changelog. If you use the “include” tag and only have preconditions on the child changelog, those preconditions will not be checked until the migrator reaches that file. This behavior may change in future releases, so don't rely on this behavior.
