Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2011 Leo Przybylski. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Leo Przybylski.
package org.kualigan.tools.liquibase;
import liquibase.change.Change;
import liquibase.change.ColumnConfig;
import liquibase.change.ConstraintsConfig;
import liquibase.change.core.*;
import liquibase.changelog.ChangeSet;
import liquibase.database.Database;
import liquibase.database.jvm.JdbcConnection;
import liquibase.database.structure.*;
import liquibase.database.typeconversion.TypeConverter;
import liquibase.database.typeconversion.TypeConverterFactory;
import liquibase.diff.*;
import liquibase.exception.DatabaseException;
import liquibase.executor.ExecutorService;
import liquibase.logging.LogFactory;
import liquibase.parser.core.xml.LiquibaseEntityResolver;
import liquibase.parser.core.xml.XMLChangeLogSAXParser;
import liquibase.serializer.ChangeLogSerializer;
import liquibase.serializer.ChangeLogSerializerFactory;
import liquibase.serializer.core.xml.XMLChangeLogSerializer;
import liquibase.snapshot.DatabaseSnapshot;
import liquibase.statement.DatabaseFunction;
import liquibase.statement.core.RawSqlStatement;
import liquibase.statement.ext.DescribeSequenceStatement;
import liquibase.util.ISODateFormat;
import liquibase.util.StringUtils;
import liquibase.util.csv.CSVWriter;
import liquibase.util.xml.DefaultXmlWriter;
import liquibase.util.xml.XmlWriter;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.*;
public class DiffResult {
private String idRoot = String.valueOf(new Date().getTime());
private int changeNumber = 1;
private DatabaseSnapshot referenceSnapshot;
private DatabaseSnapshot targetSnapshot;
private DiffComparison productName;
private DiffComparison productVersion;
private SortedSet
missingTables = new TreeSet
();
private SortedSet
unexpectedTables = new TreeSet
();
private SortedSet missingViews = new TreeSet();
private SortedSet unexpectedViews = new TreeSet();
private SortedSet changedViews = new TreeSet();
private SortedSet missingColumns = new TreeSet();
private SortedSet unexpectedColumns = new TreeSet();
private SortedSet changedColumns = new TreeSet();
private SortedSet missingForeignKeys = new TreeSet();
private SortedSet unexpectedForeignKeys = new TreeSet();
private SortedSet missingIndexes = new TreeSet();
private SortedSet unexpectedIndexes = new TreeSet();
private SortedSet missingPrimaryKeys = new TreeSet();
private SortedSet unexpectedPrimaryKeys = new TreeSet();
private SortedSet missingUniqueConstraints = new TreeSet();
private SortedSet unexpectedUniqueConstraints = new TreeSet();
private SortedSet missingSequences = new TreeSet();
private SortedSet unexpectedSequences = new TreeSet();
private boolean diffData = false;
private String dataDir = null;
private String changeSetContext;
private String changeSetAuthor;
private ChangeLogSerializerFactory serializerFactory = ChangeLogSerializerFactory.getInstance();
public DiffResult(DatabaseSnapshot referenceDatabaseSnapshot,
DatabaseSnapshot targetDatabaseSnapshot) {
this.referenceSnapshot = referenceDatabaseSnapshot;
if (targetDatabaseSnapshot == null) {
targetDatabaseSnapshot = new DatabaseSnapshot(
referenceDatabaseSnapshot.getDatabase(), null);
}
this.targetSnapshot = targetDatabaseSnapshot;
}
public DiffComparison getProductName() {
return productName;
}
public void setProductName(DiffComparison productName) {
this.productName = productName;
}
public DiffComparison getProductVersion() {
return productVersion;
}
public void setProductVersion(DiffComparison product) {
this.productVersion = product;
}
public void addMissingTable(Table table) {
missingTables.add(table);
}
public SortedSet
getMissingTables() {
return missingTables;
}
public void addUnexpectedTable(Table table) {
unexpectedTables.add(table);
}
public SortedSet
getUnexpectedTables() {
return unexpectedTables;
}
public void addMissingView(View viewName) {
missingViews.add(viewName);
}
public SortedSet getMissingViews() {
return missingViews;
}
public void addUnexpectedView(View viewName) {
unexpectedViews.add(viewName);
}
public SortedSet getUnexpectedViews() {
return unexpectedViews;
}
public void addChangedView(View viewName) {
changedViews.add(viewName);
}
public SortedSet getChangedViews() {
return changedViews;
}
public void addMissingColumn(Column columnName) {
missingColumns.add(columnName);
}
public SortedSet getMissingColumns() {
return missingColumns;
}
public void addUnexpectedColumn(Column columnName) {
unexpectedColumns.add(columnName);
}
public SortedSet getUnexpectedColumns() {
return unexpectedColumns;
}
public void addChangedColumn(Column columnName) {
changedColumns.add(columnName);
}
public SortedSet getChangedColumns() {
return changedColumns;
}
public void addMissingForeignKey(ForeignKey fkName) {
missingForeignKeys.add(fkName);
}
public SortedSet getMissingForeignKeys() {
return missingForeignKeys;
}
public void addUnexpectedForeignKey(ForeignKey fkName) {
unexpectedForeignKeys.add(fkName);
}
public SortedSet getUnexpectedForeignKeys() {
return unexpectedForeignKeys;
}
public void addMissingIndex(Index fkName) {
missingIndexes.add(fkName);
}
public SortedSet getMissingIndexes() {
return missingIndexes;
}
public void addUnexpectedIndex(Index fkName) {
unexpectedIndexes.add(fkName);
}
public SortedSet getUnexpectedIndexes() {
return unexpectedIndexes;
}
public void addMissingPrimaryKey(PrimaryKey primaryKey) {
missingPrimaryKeys.add(primaryKey);
}
public SortedSet getMissingPrimaryKeys() {
return missingPrimaryKeys;
}
public void addUnexpectedPrimaryKey(PrimaryKey primaryKey) {
unexpectedPrimaryKeys.add(primaryKey);
}
public SortedSet getUnexpectedPrimaryKeys() {
return unexpectedPrimaryKeys;
}
public void addMissingSequence(Sequence sequence) {
missingSequences.add(sequence);
}
public SortedSet getMissingSequences() {
return missingSequences;
}
public void addUnexpectedSequence(Sequence sequence) {
unexpectedSequences.add(sequence);
}
public SortedSet getUnexpectedSequences() {
return unexpectedSequences;
}
public void addMissingUniqueConstraint(UniqueConstraint uniqueConstraint) {
missingUniqueConstraints.add(uniqueConstraint);
}
public SortedSet getMissingUniqueConstraints() {
return this.missingUniqueConstraints;
}
public void addUnexpectedUniqueConstraint(UniqueConstraint uniqueConstraint) {
unexpectedUniqueConstraints.add(uniqueConstraint);
}
public SortedSet getUnexpectedUniqueConstraints() {
return unexpectedUniqueConstraints;
}
public boolean shouldDiffData() {
return diffData;
}
public void setDiffData(boolean diffData) {
this.diffData = diffData;
}
public String getDataDir() {
return dataDir;
}
public void setDataDir(String dataDir) {
this.dataDir = dataDir;
}
public String getChangeSetContext() {
return changeSetContext;
}
public void setChangeSetContext(String changeSetContext) {
this.changeSetContext = changeSetContext;
}
public boolean differencesFound() throws DatabaseException,IOException{
boolean differencesInData=false;
if(shouldDiffData()) {
List changeSets = new ArrayList();
addInsertDataChanges(changeSets, dataDir);
differencesInData=!changeSets.isEmpty();
}
return getMissingColumns().size()>0 ||
getMissingForeignKeys().size()>0 ||
getMissingIndexes().size()>0 ||
getMissingPrimaryKeys().size()>0 ||
getMissingSequences().size()>0 ||
getMissingTables().size()>0 ||
getMissingUniqueConstraints().size()>0 ||
getMissingViews().size()>0 ||
getUnexpectedColumns().size()>0 ||
getUnexpectedForeignKeys().size()>0 ||
getUnexpectedIndexes().size()>0 ||
getUnexpectedPrimaryKeys().size()>0 ||
getUnexpectedSequences().size()>0 ||
getUnexpectedTables().size()>0 ||
getUnexpectedUniqueConstraints().size()>0 ||
getUnexpectedViews().size()>0 ||
differencesInData;
}
public void printResult(PrintStream out) throws DatabaseException {
out.println("Reference Database: " + referenceSnapshot.getDatabase());
out.println("Target Database: " + targetSnapshot.getDatabase());
printComparision("Product Name", productName, out);
printComparision("Product Version", productVersion, out);
printSetComparison("Missing Tables", getMissingTables(), out);
printSetComparison("Unexpected Tables", getUnexpectedTables(), out);
printSetComparison("Missing Views", getMissingViews(), out);
printSetComparison("Unexpected Views", getUnexpectedViews(), out);
printSetComparison("Changed Views", getChangedViews(), out);
printSetComparison("Missing Columns", getMissingColumns(), out);
printSetComparison("Unexpected Columns", getUnexpectedColumns(), out);
printColumnComparison(getChangedColumns(), out);
printSetComparison("Missing Foreign Keys", getMissingForeignKeys(), out);
printSetComparison("Unexpected Foreign Keys",
getUnexpectedForeignKeys(), out);
printSetComparison("Missing Primary Keys", getMissingPrimaryKeys(), out);
printSetComparison("Unexpected Primary Keys",
getUnexpectedPrimaryKeys(), out);
printSetComparison("Unexpected Unique Constraints",
getUnexpectedUniqueConstraints(), out);
printSetComparison("Missing Unique Constraints",
getMissingUniqueConstraints(), out);
printSetComparison("Missing Indexes", getMissingIndexes(), out);
printSetComparison("Unexpected Indexes", getUnexpectedIndexes(), out);
printSetComparison("Missing Sequences", getMissingSequences(), out);
printSetComparison("Unexpected Sequences", getUnexpectedSequences(),
out);
}
private void printSetComparison(String title, SortedSet> objects,
PrintStream out) {
out.print(title + ": ");
if (objects.size() == 0) {
out.println("NONE");
} else {
out.println();
for (Object object : objects) {
out.println(" " + object);
}
}
}
private void printColumnComparison(SortedSet changedColumns,
PrintStream out) {
out.print("Changed Columns: ");
if (changedColumns.size() == 0) {
out.println("NONE");
} else {
out.println();
for (Column column : changedColumns) {
out.println(" " + column);
Column baseColumn = referenceSnapshot.getColumn(column
.getTable().getName(), column.getName());
if (baseColumn != null) {
if (baseColumn.isDataTypeDifferent(column)) {
out.println(" from "
+ TypeConverterFactory.getInstance().findTypeConverter(referenceSnapshot.getDatabase()).convertToDatabaseTypeString(baseColumn, referenceSnapshot.getDatabase())
+ " to "
+ TypeConverterFactory.getInstance().findTypeConverter(targetSnapshot.getDatabase()).convertToDatabaseTypeString(targetSnapshot.getColumn(column.getTable().getName(), column.getName()), targetSnapshot.getDatabase()));
}
if (baseColumn.isNullabilityDifferent(column)) {
Boolean nowNullable = targetSnapshot.getColumn(
column.getTable().getName(), column.getName())
.isNullable();
if (nowNullable == null) {
nowNullable = Boolean.TRUE;
}
if (nowNullable) {
out.println(" now nullable");
} else {
out.println(" now not null");
}
}
}
}
}
}
private void printComparision(String title, DiffComparison comparison, PrintStream out) {
out.print(title + ":");
if (comparison == null) {
out.print("NULL");
return;
}
if (comparison.areTheSame()) {
out.println(" EQUAL");
} else {
out.println();
out.println(" Reference: '"
+ comparison.getReferenceVersion() + "'");
out.println(" Target: '" + comparison.getTargetVersion() + "'");
}
}
public void printChangeLog(String changeLogFile, Database targetDatabase)
throws ParserConfigurationException, IOException, DatabaseException {
ChangeLogSerializer changeLogSerializer = serializerFactory.getSerializer(changeLogFile);
this.printChangeLog(changeLogFile, targetDatabase, changeLogSerializer);
}
public void printChangeLog(PrintStream out, Database targetDatabase)
throws ParserConfigurationException, IOException, DatabaseException {
this.printChangeLog(out, targetDatabase, new XMLChangeLogSerializer());
}
public void printChangeLog(String changeLogFile, Database targetDatabase,
ChangeLogSerializer changeLogSerializer) throws ParserConfigurationException,
IOException, DatabaseException {
File file = new File(changeLogFile);
if (!file.exists()) {
LogFactory.getLogger().info(file + " does not exist, creating");
FileOutputStream stream = new FileOutputStream(file);
printChangeLog(new PrintStream(stream), targetDatabase, changeLogSerializer);
stream.close();
} else {
LogFactory.getLogger().info(file + " exists, appending");
ByteArrayOutputStream out = new ByteArrayOutputStream();
printChangeLog(new PrintStream(out), targetDatabase, changeLogSerializer);
String xml = new String(out.toByteArray());
xml = xml.replaceFirst("(?ms).*]*>", "");
xml = xml.replaceFirst("", "");
xml = xml.trim();
if ("".equals( xml )) {
LogFactory.getLogger().info("No changes found, nothing to do");
return;
}
String lineSeparator = System.getProperty("line.separator");
BufferedReader fileReader = new BufferedReader(new FileReader(file));
String line;
long offset = 0;
while ((line = fileReader.readLine()) != null) {
int index = line.indexOf("");
if (index >= 0) {
offset += index;
} else {
offset += line.getBytes().length;
offset += lineSeparator.getBytes().length;
}
}
fileReader.close();
fileReader = new BufferedReader(new FileReader(file));
fileReader.skip(offset);
fileReader.close();
// System.out.println("resulting XML: " + xml.trim());
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
randomAccessFile.seek(offset);
randomAccessFile.writeBytes(" ");
randomAccessFile.write( xml.getBytes() );
randomAccessFile.writeBytes(lineSeparator);
randomAccessFile.writeBytes("" + lineSeparator);
randomAccessFile.close();
// BufferedWriter fileWriter = new BufferedWriter(new
// FileWriter(file));
// fileWriter.append(xml);
// fileWriter.close();
}
}
/**
* Prints changeLog that would bring the target database to be the same as
* the reference database
*/
public void printChangeLog(PrintStream out, Database targetDatabase,
ChangeLogSerializer changeLogSerializer)
throws ParserConfigurationException,
IOException, DatabaseException {
List changeSets = new ArrayList();
addMissingTableChanges(changeSets, targetDatabase);
addMissingColumnChanges(changeSets, targetDatabase);
addChangedColumnChanges(changeSets);
addMissingPrimaryKeyChanges(changeSets);
addUnexpectedPrimaryKeyChanges(changeSets);
addUnexpectedForeignKeyChanges(changeSets);
addMissingUniqueConstraintChanges(changeSets);
addMissingIndexChanges(changeSets);
addUnexpectedUniqueConstraintChanges(changeSets);
if (diffData) {
addInsertDataChanges(changeSets, dataDir);
}
addMissingForeignKeyChanges(changeSets);
addUnexpectedIndexChanges(changeSets);
addUnexpectedColumnChanges(changeSets);
addMissingSequenceChanges(changeSets);
addUnexpectedSequenceChanges(changeSets);
addMissingViewChanges(changeSets);
addUnexpectedViewChanges(changeSets);
addChangedViewChanges(changeSets);
addUnexpectedTableChanges(changeSets);
changeLogSerializer.write(changeSets, out);
out.flush();
}
private ChangeSet generateChangeSet(Change change) {
ChangeSet changeSet = generateChangeSet();
changeSet.addChange(change);
return changeSet;
}
private ChangeSet generateChangeSet() {
return new ChangeSet(generateId(), getChangeSetAuthor(), false, false,
null, getChangeSetContext(), null);
}
private String getChangeSetAuthor() {
if (changeSetAuthor != null) {
return changeSetAuthor;
}
String author = System.getProperty("user.name");
if (StringUtils.trimToNull(author) == null) {
return "diff-generated";
} else {
return author + " (generated)";
}
}
public void setChangeSetAuthor(String changeSetAuthor) {
this.changeSetAuthor = changeSetAuthor;
}
public void setIdRoot(String idRoot) {
this.idRoot = idRoot;
}
protected String generateId() {
return idRoot + "-" + changeNumber++;
}
private void addUnexpectedIndexChanges(List changes) {
for (Index index : getUnexpectedIndexes()) {
if (index.getAssociatedWith().contains(Index.MARK_PRIMARY_KEY) || index.getAssociatedWith().contains(Index.MARK_FOREIGN_KEY) || index.getAssociatedWith().contains(Index.MARK_UNIQUE_CONSTRAINT)) {
continue;
}
DropIndexChange change = new DropIndexChange();
change.setTableName(index.getTable().getName());
change.setSchemaName(index.getTable().getSchema());
change.setIndexName(index.getName());
change.setAssociatedWith(index.getAssociatedWithAsString());
changes.add(generateChangeSet(change));
}
}
private void addMissingIndexChanges(List changes) {
for (Index index : getMissingIndexes()) {
CreateIndexChange change = new CreateIndexChange();
change.setTableName(index.getTable().getName());
change.setTablespace(index.getTablespace());
change.setSchemaName(index.getTable().getSchema());
change.setIndexName(index.getName());
change.setUnique(index.isUnique());
change.setAssociatedWith(index.getAssociatedWithAsString());
if (index.getAssociatedWith().contains(Index.MARK_PRIMARY_KEY) || index.getAssociatedWith().contains(Index.MARK_FOREIGN_KEY) || index.getAssociatedWith().contains(Index.MARK_UNIQUE_CONSTRAINT)) {
continue;
}
for (String columnName : index.getColumns()) {
ColumnConfig column = new ColumnConfig();
column.setName(columnName);
change.addColumn(column);
}
changes.add(generateChangeSet(change));
}
}
private void addUnexpectedPrimaryKeyChanges(List changes) {
for (PrimaryKey pk : getUnexpectedPrimaryKeys()) {
if (!getUnexpectedTables().contains(pk.getTable())) {
DropPrimaryKeyChange change = new DropPrimaryKeyChange();
change.setTableName(pk.getTable().getName());
change.setSchemaName(pk.getTable().getSchema());
change.setConstraintName(pk.getName());
changes.add(generateChangeSet(change));
}
}
}
private void addMissingPrimaryKeyChanges(List changes) {
for (PrimaryKey pk : getMissingPrimaryKeys()) {
AddPrimaryKeyChange change = new AddPrimaryKeyChange();
change.setTableName(pk.getTable().getName());
change.setSchemaName(pk.getTable().getSchema());
change.setConstraintName(pk.getName());
change.setColumnNames(pk.getColumnNames());
change.setTablespace(pk.getTablespace());
changes.add(generateChangeSet(change));
}
}
private void addUnexpectedUniqueConstraintChanges(List changes) {
for (UniqueConstraint uc : getUnexpectedUniqueConstraints()) {
// Need check for nulls here due to NullPointerException using Postgres
if (null != uc) {
if (null != uc.getTable()) {
DropUniqueConstraintChange change = new DropUniqueConstraintChange();
change.setTableName(uc.getTable().getName());
change.setSchemaName(uc.getTable().getSchema());
change.setConstraintName(uc.getName());
changes.add(generateChangeSet(change));
}
}
}
}
private void addMissingUniqueConstraintChanges(List changes) {
for (UniqueConstraint uc : getMissingUniqueConstraints()) {
// Need check for nulls here due to NullPointerException using Postgres
if (null != uc)
if (null != uc.getTable()) {
AddUniqueConstraintChange change = new AddUniqueConstraintChange();
change.setTableName(uc.getTable().getName());
change.setTablespace(uc.getTablespace());
change.setSchemaName(uc.getTable().getSchema());
change.setConstraintName(uc.getName());
change.setColumnNames(uc.getColumnNames());
change.setDeferrable(uc.isDeferrable());
change.setInitiallyDeferred(uc.isInitiallyDeferred());
change.setDisabled(uc.isDisabled());
changes.add(generateChangeSet(change));
}
}
}
private void addUnexpectedForeignKeyChanges(List changes) {
for (ForeignKey fk : getUnexpectedForeignKeys()) {
DropForeignKeyConstraintChange change = new DropForeignKeyConstraintChange();
change.setConstraintName(fk.getName());
change.setBaseTableName(fk.getForeignKeyTable().getName());
change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema());
changes.add(generateChangeSet(change));
}
}
private void addMissingForeignKeyChanges(List changes) {
for (ForeignKey fk : getMissingForeignKeys()) {
AddForeignKeyConstraintChange change = new AddForeignKeyConstraintChange();
change.setConstraintName(fk.getName());
change.setReferencedTableName(fk.getPrimaryKeyTable().getName());
change.setReferencedTableSchemaName(fk.getPrimaryKeyTable()
.getSchema());
change.setReferencedColumnNames(fk.getPrimaryKeyColumns());
change.setBaseTableName(fk.getForeignKeyTable().getName());
change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema());
change.setBaseColumnNames(fk.getForeignKeyColumns());
change.setDeferrable(fk.isDeferrable());
change.setInitiallyDeferred(fk.isInitiallyDeferred());
change.setOnUpdate(fk.getUpdateRule());
change.setOnDelete(fk.getDeleteRule());
change.setReferencesUniqueColumn(fk.getReferencesUniqueColumn());
changes.add(generateChangeSet(change));
}
}
private void addUnexpectedSequenceChanges(List changes) {
for (Sequence sequence : getUnexpectedSequences()) {
DropSequenceChange change = new DropSequenceChange();
change.setSequenceName(sequence.getName());
change.setSchemaName(sequence.getSchema());
changes.add(generateChangeSet(change));
}
}
private void addMissingSequenceChanges(List changes) {
for (Sequence sequence : getMissingSequences()) {
CreateSequenceChange change = new CreateSequenceChange();
change.setSequenceName(sequence.getName());
change.setSchemaName(sequence.getSchema());
try {
final DescribeSequenceStatement statement = new DescribeSequenceStatement(sequence.getName());
final BigInteger startValue = (BigInteger) ExecutorService.getInstance().getExecutor(referenceSnapshot.getDatabase()).queryForObject(statement, BigInteger.class);
change.setStartValue(startValue);
}
catch (Exception e) {
e.printStackTrace();
// quietly don't set start value
}
changes.add(generateChangeSet(change));
}
}
private void addUnexpectedColumnChanges(List changes) {
for (Column column : getUnexpectedColumns()) {
if (!shouldModifyColumn(column)) {
continue;
}
DropColumnChange change = new DropColumnChange();
change.setTableName(column.getTable().getName());
change.setSchemaName(column.getTable().getSchema());
change.setColumnName(column.getName());
changes.add(generateChangeSet(change));
}
}
private void addMissingViewChanges(List changes) {
for (View view : getMissingViews()) {
CreateViewChange change = new CreateViewChange();
change.setViewName(view.getName());
change.setSchemaName(view.getSchema());
String selectQuery = view.getDefinition();
if (selectQuery == null) {
selectQuery = "COULD NOT DETERMINE VIEW QUERY";
}
change.setSelectQuery(selectQuery);
changes.add(generateChangeSet(change));
}
}
private void addChangedViewChanges(List changes) {
for (View view : getChangedViews()) {
CreateViewChange change = new CreateViewChange();
change.setViewName(view.getName());
change.setSchemaName(view.getSchema());
String selectQuery = view.getDefinition();
if (selectQuery == null) {
selectQuery = "COULD NOT DETERMINE VIEW QUERY";
}
change.setSelectQuery(selectQuery);
change.setReplaceIfExists(true);
changes.add(generateChangeSet(change));
}
}
private void addChangedColumnChanges(List changes) {
for (Column column : getChangedColumns()) {
if (!shouldModifyColumn(column)) {
continue;
}
TypeConverter targetTypeConverter = TypeConverterFactory.getInstance().findTypeConverter(targetSnapshot.getDatabase());
boolean foundDifference = false;
Column referenceColumn = referenceSnapshot.getColumn(column.getTable().getName(), column.getName());
if (column.isDataTypeDifferent(referenceColumn)) {
ModifyDataTypeChange change = new ModifyDataTypeChange();
change.setTableName(column.getTable().getName());
change.setSchemaName(column.getTable().getSchema());
change.setColumnName(column.getName());
change.setNewDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn, targetSnapshot.getDatabase()));
changes.add(generateChangeSet(change));
foundDifference = true;
}
if (column.isNullabilityDifferent(referenceColumn)) {
if (referenceColumn.isNullable() == null
|| referenceColumn.isNullable()) {
DropNotNullConstraintChange change = new DropNotNullConstraintChange();
change.setTableName(column.getTable().getName());
change.setSchemaName(column.getTable().getSchema());
change.setColumnName(column.getName());
change.setColumnDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn, targetSnapshot.getDatabase()));
changes.add(generateChangeSet(change));
foundDifference = true;
} else {
AddNotNullConstraintChange change = new AddNotNullConstraintChange();
change.setTableName(column.getTable().getName());
change.setSchemaName(column.getTable().getSchema());
change.setColumnName(column.getName());
change.setColumnDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn, targetSnapshot.getDatabase()));
Object defaultValue = column.getDefaultValue();
String defaultValueString;
if (defaultValue != null) {
defaultValueString = targetTypeConverter.getDataType(defaultValue).convertObjectToString(defaultValue, targetSnapshot.getDatabase());
if (defaultValueString != null) {
change.setDefaultNullValue(defaultValueString);
}
}
changes.add(generateChangeSet(change));
foundDifference = true;
}
}
if (!foundDifference) {
throw new RuntimeException("Unknown difference");
}
}
}
private boolean shouldModifyColumn(Column column) {
return column.getView() == null
&& !referenceSnapshot.getDatabase().isLiquibaseTable(
column.getTable().getName());
}
private void addUnexpectedViewChanges(List changes) {
for (View view : getUnexpectedViews()) {
DropViewChange change = new DropViewChange();
change.setViewName(view.getName());
change.setSchemaName(view.getSchema());
changes.add(generateChangeSet(change));
}
}
private void addMissingColumnChanges(List changes,
Database database) {
for (Column column : getMissingColumns()) {
if (!shouldModifyColumn(column)) {
continue;
}
AddColumnChange change = new AddColumnChange();
change.setTableName(column.getTable().getName());
change.setSchemaName(column.getTable().getSchema());
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setName(column.getName());
String dataType = TypeConverterFactory.getInstance().findTypeConverter(database).convertToDatabaseTypeString(column, database);
columnConfig.setType(dataType);
Object defaultValue = column.getDefaultValue();
if (defaultValue != null) {
String defaultValueString = TypeConverterFactory.getInstance()
.findTypeConverter(database).getDataType(defaultValue)
.convertObjectToString(defaultValue, database);
if (defaultValueString != null) {
defaultValueString = defaultValueString.replaceFirst("'",
"").replaceAll("'$", "");
}
columnConfig.setDefaultValue(defaultValueString);
}
if (column.getRemarks() != null) {
columnConfig.setRemarks(column.getRemarks());
}
ConstraintsConfig constraintsConfig = columnConfig.getConstraints();
if (column.isNullable() != null && !column.isNullable()) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setNullable(false);
}
if (column.isUnique()) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setUnique(true);
}
if (constraintsConfig != null) {
columnConfig.setConstraints(constraintsConfig);
}
change.addColumn(columnConfig);
changes.add(generateChangeSet(change));
}
}
private void addMissingTableChanges(List changes,
Database database) {
for (Table missingTable : getMissingTables()) {
if (referenceSnapshot.getDatabase().isLiquibaseTable(
missingTable.getName())) {
continue;
}
CreateTableChange change = new CreateTableChange();
change.setTableName(missingTable.getName());
change.setSchemaName(missingTable.getSchema());
if (missingTable.getRemarks() != null) {
change.setRemarks(missingTable.getRemarks());
}
for (Column column : missingTable.getColumns()) {
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setName(column.getName());
columnConfig.setType(TypeConverterFactory.getInstance().findTypeConverter(database).convertToDatabaseTypeString(column, database));
ConstraintsConfig constraintsConfig = null;
if (column.isPrimaryKey()) {
PrimaryKey primaryKey = null;
for (PrimaryKey pk : getMissingPrimaryKeys()) {
if (pk.getTable().getName().equalsIgnoreCase(missingTable.getName())) {
primaryKey = pk;
}
}
if (primaryKey == null || primaryKey.getColumnNamesAsList().size() == 1) {
constraintsConfig = new ConstraintsConfig();
constraintsConfig.setPrimaryKey(true);
constraintsConfig.setPrimaryKeyTablespace(column.getTablespace());
if (primaryKey != null) {
constraintsConfig.setPrimaryKeyName(primaryKey.getName());
getMissingPrimaryKeys().remove(primaryKey);
}
}
}
if (column.isAutoIncrement()) {
columnConfig.setAutoIncrement(true);
}
if (column.isNullable() != null && !column.isNullable()) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setNullable(false);
}
if (column.isUnique()) {
if (constraintsConfig == null) {
constraintsConfig = new ConstraintsConfig();
}
constraintsConfig.setUnique(true);
}
if (constraintsConfig != null) {
columnConfig.setConstraints(constraintsConfig);
}
Object defaultValue = column.getDefaultValue();
if (defaultValue == null) {
// do nothing
} else if (column.isAutoIncrement()) {
// do nothing
} else if (defaultValue instanceof Date) {
columnConfig.setDefaultValueDate((Date) defaultValue);
} else if (defaultValue instanceof Boolean) {
columnConfig.setDefaultValueBoolean(((Boolean) defaultValue));
} else if (defaultValue instanceof Number) {
columnConfig.setDefaultValueNumeric(((Number) defaultValue));
} else if (defaultValue instanceof DatabaseFunction) {
columnConfig.setDefaultValueComputed((DatabaseFunction) defaultValue);
} else {
columnConfig.setDefaultValue(defaultValue.toString());
}
if (column.getRemarks() != null) {
columnConfig.setRemarks(column.getRemarks());
}
change.addColumn(columnConfig);
}
changes.add(generateChangeSet(change));
}
}
private void addUnexpectedTableChanges(List changes) {
for (Table unexpectedTable : getUnexpectedTables()) {
DropTableChange change = new DropTableChange();
change.setTableName(unexpectedTable.getName());
change.setSchemaName(unexpectedTable.getSchema());
changes.add(generateChangeSet(change));
}
}
private void addInsertDataChanges(List changeSets, String dataDir)
throws DatabaseException, IOException {
try {
String schema = referenceSnapshot.getSchema();
for (Table table : referenceSnapshot.getTables()) {
List changes = new ArrayList();
List