All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kualigan.tools.liquibase.DiffResult.txt Maven / Gradle / Ivy

/*
 * Copyright 2005-2007 The Kuali Foundation
 *
 *
 * Licensed under the Educational Community License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.opensource.org/licenses/ecl2.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.rsmart.kuali.tools.liquibase;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.sql.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import liquibase.change.*;

import liquibase.csv.CSVWriter;
import liquibase.database.Database;
import liquibase.database.HsqlDatabase;
import liquibase.database.OracleDatabase;
import liquibase.database.structure.*;
import liquibase.diff.DiffComparison;
import liquibase.exception.JDBCException;
import liquibase.log.LogFactory;
import liquibase.parser.LiquibaseSchemaResolver;
import liquibase.parser.xml.XMLChangeLogParser;
import liquibase.util.SqlUtil;
import liquibase.util.StringUtils;
import liquibase.xml.DefaultXmlWriter;
import liquibase.xml.XmlWriter;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class DiffResult {

    private Long baseId = new Date().getTime();
    private int changeNumber = 1;

    private Database baseDatabase;
    private Database targetDatabase;

    private DatabaseSnapshot baseSnapshot;
    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 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; public DiffResult(DatabaseSnapshot baseDatabase, DatabaseSnapshot targetDatabase) { this.baseDatabase = baseDatabase.getDatabase(); this.targetDatabase = targetDatabase.getDatabase(); this.baseSnapshot = baseDatabase; this.targetSnapshot = targetDatabase; } 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 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 void printResult(PrintStream out) throws JDBCException { out.println("Base Database: " + targetDatabase.getConnectionUsername() + " " + targetDatabase.getConnectionURL()); out.println("Target Database: " + baseDatabase.getConnectionUsername() + " " + baseDatabase.getConnectionURL()); 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("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("Missing Unique Constraints", getMissingUniqueConstraints(), out); printSetComparison("Unexpected Unique Constraints", getUnexpectedUniqueConstraints(), 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 = baseSnapshot.getColumn(column); if (baseColumn != null) { if (baseColumn.isDataTypeDifferent(column)) { out.println(" from " + baseColumn.getDataTypeString(baseDatabase) + " to " + targetSnapshot.getColumn(column).getDataTypeString(targetDatabase)); } if (baseColumn.isNullabilityDifferent(column)) { Boolean nowNullable = targetSnapshot.getColumn(column).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.areTheSame()) { out.println(" EQUAL"); } else { out.println(); out.println(" Base: '" + comparison.getBaseVersion() + "'"); out.println(" Target: '" + comparison.getTargetVersion() + "'"); } } public void printChangeLog(String changeLogFile, Database targetDatabase) throws ParserConfigurationException, IOException, JDBCException { this.printChangeLog(changeLogFile, targetDatabase, new DefaultXmlWriter()); } public void printChangeLog(PrintStream out, Database targetDatabase) throws ParserConfigurationException, IOException, JDBCException { this.printChangeLog(out, targetDatabase, new DefaultXmlWriter()); } public void printChangeLog(String changeLogFile, Database targetDatabase, XmlWriter xmlWriter) throws ParserConfigurationException, IOException, JDBCException { 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, xmlWriter); stream.close(); } else { LogFactory.getLogger().info(file + " exists, appending"); ByteArrayOutputStream out = new ByteArrayOutputStream(); printChangeLog(new PrintStream(out), targetDatabase, xmlWriter); String xml = new String(out.toByteArray()); xml = xml.replaceFirst("(?ms).*]*>", ""); xml = xml.replaceFirst("", ""); xml = xml.trim(); 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(" " + xml + lineSeparator); randomAccessFile.writeBytes("" + lineSeparator); randomAccessFile.close(); // BufferedWriter fileWriter = new BufferedWriter(new FileWriter(file)); // fileWriter.append(xml); // fileWriter.close(); } } /** * Prints changeLog that would bring the base database to be the same as the target database */ public void printChangeLog(PrintStream out, Database targetDatabase, XmlWriter xmlWriter) throws ParserConfigurationException, IOException, JDBCException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = factory.newDocumentBuilder(); documentBuilder.setEntityResolver(new LiquibaseSchemaResolver()); Document doc = documentBuilder.newDocument(); Element changeLogElement = doc.createElement("databaseChangeLog"); changeLogElement.setAttribute("xmlns", "http://www.liquibase.org/xml/ns/dbchangelog/" + XMLChangeLogParser.getSchemaVersion()); changeLogElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); changeLogElement.setAttribute("xsi:schemaLocation", "http://www.liquibase.org/xml/ns/dbchangelog/" + XMLChangeLogParser.getSchemaVersion() + " http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-" + XMLChangeLogParser.getSchemaVersion() + ".xsd"); doc.appendChild(changeLogElement); List changes = new ArrayList(); addUnexpectedViewChanges(changes); addMissingTableChanges(changes, targetDatabase); addMissingColumnChanges(changes, targetDatabase); addChangedColumnChanges(changes); addMissingPrimaryKeyChanges(changes); addUnexpectedPrimaryKeyChanges(changes); addMissingUniqueConstraintChanges(changes); addUnexpectedUniqueConstraintChanges(changes); addMissingIndexChanges(changes); addUnexpectedIndexChanges(changes); if (diffData) { addInsertDataChanges(changes, dataDir); } addMissingForeignKeyChanges(changes); addUnexpectedForeignKeyChanges(changes); addUnexpectedColumnChanges(changes); addMissingSequenceChanges(changes); addUnexpectedSequenceChanges(changes); addMissingViewChanges(changes); addUnexpectedTableChanges(changes); for (Change change : changes) { Element changeSet = doc.createElement("changeSet"); changeSet.setAttribute("author", getChangeSetAuthor()); changeSet.setAttribute("id", generateId()); if (getChangeSetContext() != null) { changeSet.setAttribute("context", getChangeSetContext()); } changeSet.appendChild(change.createNode(doc)); doc.getDocumentElement().appendChild(changeSet); } xmlWriter.write(doc, out); out.flush(); } 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; } private String generateId() { return baseId.toString() + "-" + changeNumber++; } private void addUnexpectedIndexChanges(List changes) { for (Index index : getUnexpectedIndexes()) { DropIndexChange change = new DropIndexChange(); change.setTableName(index.getTable().getName()); change.setIndexName(index.getName()); changes.add(change); } } private void addMissingIndexChanges(List changes) { for (Index index : getMissingIndexes()) { CreateIndexChange change = new CreateIndexChange(); change.setTableName(index.getTable().getName()); change.setIndexName(index.getName()); change.setUnique(index.isUnique()); for (String columnName : index.getColumns()) { ColumnConfig column = new ColumnConfig(); column.setName(columnName); change.addColumn(column); } changes.add(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.setConstraintName(pk.getName()); changes.add(change); } } } private void addMissingPrimaryKeyChanges(List changes) { for (PrimaryKey pk : getMissingPrimaryKeys()) { AddPrimaryKeyChange change = new AddPrimaryKeyChange(); change.setTableName(pk.getTable().getName()); change.setConstraintName(pk.getName()); change.setColumnNames(pk.getColumnNames()); changes.add(change); } } private void addUnexpectedUniqueConstraintChanges(List changes) { for (UniqueConstraint uc : getUnexpectedUniqueConstraints()) { if (!getUnexpectedTables().contains(uc.getTable())) { DropUniqueConstraintChange change = new DropUniqueConstraintChange(); change.setTableName(uc.getTable().getName()); change.setConstraintName(uc.getName()); changes.add(change); } } } private void addMissingUniqueConstraintChanges(List changes) { for (UniqueConstraint uc : getMissingUniqueConstraints()) { AddUniqueConstraintChange change = new AddUniqueConstraintChange(); change.setTableName(uc.getTable().getName()); change.setConstraintName(uc.getName()); change.setColumnNames(uc.getColumnNames()); changes.add(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(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.setUpdateRule(fk.getUpdateRule()); change.setDeleteRule(fk.getDeleteRule()); changes.add(change); } } private void addUnexpectedSequenceChanges(List changes) { for (Sequence sequence : getUnexpectedSequences()) { DropSequenceChange change = new DropSequenceChange(); change.setSequenceName(sequence.getName()); // change.setSchemaName(sequence.getSchema()); changes.add(change); } } private void addMissingSequenceChanges(List changes) { for (Sequence sequence : getMissingSequences()) { // change.setSchemaName(sequence.getSchema()); changes.add(setupSequenceChange(sequence)); } } private CreateSequenceChange setupSequenceChange(Sequence sequence) { CreateSequenceChange retval = new com.rsmart.kuali.tools.liquibase.CreateSequenceChange(); retval.setSequenceName(sequence.getName()); if (!(baseDatabase instanceof OracleDatabase)) return retval; try { Statement statement = baseDatabase.getConnection().createStatement(); ResultSet rs = statement.executeQuery("select * from user_sequences where sequence_name = '" + sequence.getName() + "'"); if (rs.next()) { retval.setIncrementBy(rs.getInt("INCREMENT_BY")); retval.setOrdered(rs.getString("ORDER_FLAG").equals("Y")); retval.setStartValue((int) rs.getLong("LAST_NUMBER") + 100); // retval.setMaxValue(Integer.parseInt(rs.getString("MAX_VALUE")/); } rs.close(); statement.close(); } catch (Exception e) { throw new RuntimeException(e); } return retval; } 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().getName()); change.setColumnName(column.getName()); changes.add(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(change); } } private void addChangedColumnChanges(List changes) { for (Column column : getChangedColumns()) { if (!shouldModifyColumn(column)) { continue; } boolean foundDifference = false; Column baseColumn = baseSnapshot.getColumn(column); if (column.isDataTypeDifferent(baseColumn)) { ColumnConfig columnConfig = new ColumnConfig(); columnConfig.setName(column.getName()); columnConfig.setType(baseColumn.getDataTypeString(targetDatabase)); ModifyColumnChange change = new ModifyColumnChange(); change.setTableName(column.getTable().getName()); // change.setSchemaName(column.getTable().getSchema()); change.addColumn(columnConfig); changes.add(change); foundDifference = true; } if (column.isNullabilityDifferent(baseColumn)) { if (baseColumn.isNullable() == null || baseColumn.isNullable()) { DropNotNullConstraintChange change = new DropNotNullConstraintChange(); change.setTableName(column.getTable().getName()); // change.setSchemaName(column.getTable().getSchema()); change.setColumnName(column.getName()); change.setColumnDataType(baseColumn.getDataTypeString(targetDatabase)); changes.add(change); foundDifference = true; } else { AddNotNullConstraintChange change = new AddNotNullConstraintChange(); change.setTableName(column.getTable().getName()); // change.setSchemaName(column.getTable().getSchema()); change.setColumnName(column.getName()); change.setColumnDataType(baseColumn.getDataTypeString(targetDatabase)); changes.add(change); foundDifference = true; } } if (!foundDifference) { throw new RuntimeException("Unknown difference"); } } } private boolean shouldModifyColumn(Column column) { return column.getView() == null && !baseDatabase.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(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 = column.getDataTypeString(database); columnConfig.setType(dataType); String defaultValueString = database.convertJavaObjectToString(column.getDefaultValue()); if(defaultValueString !=null) { defaultValueString = defaultValueString.replaceFirst("'","").replaceAll("'$", ""); } columnConfig.setDefaultValue(defaultValueString); if (column.getRemarks() != null) { columnConfig.setRemarks(column.getRemarks()); } if (column.isNullable() != null && !column.isNullable()) { ConstraintsConfig constraintsConfig = columnConfig.getConstraints(); if (constraintsConfig == null) { constraintsConfig = new ConstraintsConfig(); columnConfig.setConstraints(constraintsConfig); } constraintsConfig.setNullable(false); } change.addColumn(columnConfig); changes.add(change); } } private void addMissingTableChanges(List changes, Database database) { for (Table missingTable : getMissingTables()) { if (baseDatabase.isLiquibaseTable(missingTable.getName())) { continue; } CreateTableChange change = new com.rsmart.kuali.tools.liquibase.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(column.getDataTypeString(database)); if (database instanceof HsqlDatabase) { if (columnConfig.getType().startsWith("VARCHAR2")) { columnConfig.setType(columnConfig.getType().replaceFirst("VARCHAR2", "VARCHAR")); } else if (columnConfig.getType().startsWith("NUMB")) { columnConfig.setType(columnConfig.getType().replaceFirst("NUMBER", "NUMERIC")); } } 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); if (primaryKey != null) { String keyName = primaryKey.getName(); constraintsConfig.setPrimaryKeyName(keyName); 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 (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 { columnConfig.setDefaultValue(defaultValue.toString()); } if (column.getRemarks() != null) { columnConfig.setRemarks(column.getRemarks()); } if (database instanceof HsqlDatabase) { if (columnConfig.getDefaultValueDate() != null && columnConfig.getDefaultValueDate().toString().equalsIgnoreCase("SYSDATE")) { columnConfig.setDefaultValueDate((Date) null); } } change.addColumn(columnConfig); } changes.add(change); } } private void addUnexpectedTableChanges(List changes) { for (Table unexpectedTable : getUnexpectedTables()) { DropTableChange change = new DropTableChange(); change.setTableName(unexpectedTable.getName()); // change.setSchemaName(unexpectedTable.getSchema()); changes.add(change); } } private void addInsertDataChanges(List changes, String dataDir) throws JDBCException, IOException { try { String schema = baseSnapshot.getSchema(); Statement stmt = baseSnapshot.getDatabase().getConnection().createStatement(); for (Table table : baseSnapshot.getTables()) { ResultSet rs = stmt.executeQuery("SELECT * FROM " + baseSnapshot.getDatabase().escapeTableName(schema, table.getName())); ResultSetMetaData columnData = rs.getMetaData(); int columnCount = columnData.getColumnCount(); // if dataDir is not null, print out a csv file and use loadData tag if (dataDir != null) { String fileName = table.getName() + ".csv"; if (dataDir != null) { fileName = dataDir + "/" + fileName; } File parentDir = new File(dataDir); if (!parentDir.exists()) { parentDir.mkdirs(); } if (!parentDir.isDirectory()) { throw new RuntimeException(parentDir + " is not a directory"); } CSVWriter outputFile = new CSVWriter(new FileWriter(fileName)); outputFile.writeAll(rs, true); outputFile.flush(); outputFile.close(); LoadDataChange change = new LoadDataChange(); change.setFile(fileName); change.setEncoding("UTF-8"); // change.setSchemaName(schema); change.setTableName(table.getName()); for (int col = 1; col <= columnCount; col++) { String colName = columnData.getColumnName(col); int dataType = columnData.getColumnType(col); String typeString = "STRING"; if (SqlUtil.isNumeric(dataType)) { typeString = "NUMERIC"; } else if (SqlUtil.isBoolean(dataType)) { typeString = "BOOLEAN"; } else if (SqlUtil.isDate(dataType)) { typeString = "DATE"; } LoadDataColumnConfig columnConfig = new LoadDataColumnConfig(); columnConfig.setHeader(colName); columnConfig.setType(typeString); change.addColumn(columnConfig); } changes.add(change); } else { // if dataDir is null, build and use insert tags // loop over all rows while (rs.next()) { InsertDataChange change = new InsertDataChange(); // change.setSchemaName(schema); change.setTableName(table.getName()); // loop over all columns for this row for (int col = 1; col <= columnCount; col++) { ColumnConfig column = new ColumnConfig(); column.setName(columnData.getColumnName(col)); // set the value for this column int dataType = columnData.getColumnType(col); if (SqlUtil.isNumeric(dataType)) { String columnValue = rs.getString(col); if (columnValue == null) { column.setValueNumeric((Number) null); } else { // its some sort of non-null number if (dataType == Types.DOUBLE || dataType == Types.NUMERIC || dataType == Types.DECIMAL) { column.setValueNumeric(new Double(columnValue)); } else if (dataType == Types.FLOAT || dataType == Types.REAL) { column.setValueNumeric(new Float(columnValue)); } else { // its an integer type of column column.setValueNumeric(new Integer(columnValue)); } } } else if (SqlUtil.isBoolean(dataType)) { column.setValueBoolean(rs.getBoolean(col)); } else if (SqlUtil.isDate(dataType)) { column.setValueDate(rs.getDate(col)); } else { //string column.setValue(rs.getString(col)); } change.addColumn(column); } // for each row, add a new change // (there will be one group per table) changes.add(change); } } } } catch (Exception e) { throw new RuntimeException(e); } } }