Coverage Report - liquibase.diff.DiffResult
 
Classes in this File Line Coverage Branch Coverage Complexity
DiffResult
0%
0/623
0%
0/280
2.768
 
 1  
 package liquibase.diff;
 2  
 
 3  
 import java.io.BufferedReader;
 4  
 import java.io.ByteArrayOutputStream;
 5  
 import java.io.File;
 6  
 import java.io.FileOutputStream;
 7  
 import java.io.FileReader;
 8  
 import java.io.FileWriter;
 9  
 import java.io.IOException;
 10  
 import java.io.PrintStream;
 11  
 import java.io.RandomAccessFile;
 12  
 import java.util.ArrayList;
 13  
 import java.util.Date;
 14  
 import java.util.List;
 15  
 import java.util.Map;
 16  
 import java.util.SortedSet;
 17  
 import java.util.TreeSet;
 18  
 
 19  
 import javax.xml.parsers.ParserConfigurationException;
 20  
 
 21  
 import liquibase.change.Change;
 22  
 import liquibase.change.ColumnConfig;
 23  
 import liquibase.change.ConstraintsConfig;
 24  
 import liquibase.change.core.AddColumnChange;
 25  
 import liquibase.change.core.AddForeignKeyConstraintChange;
 26  
 import liquibase.change.core.AddNotNullConstraintChange;
 27  
 import liquibase.change.core.AddPrimaryKeyChange;
 28  
 import liquibase.change.core.AddUniqueConstraintChange;
 29  
 import liquibase.change.core.CreateIndexChange;
 30  
 import liquibase.change.core.CreateSequenceChange;
 31  
 import liquibase.change.core.CreateTableChange;
 32  
 import liquibase.change.core.CreateViewChange;
 33  
 import liquibase.change.core.DropColumnChange;
 34  
 import liquibase.change.core.DropForeignKeyConstraintChange;
 35  
 import liquibase.change.core.DropIndexChange;
 36  
 import liquibase.change.core.DropNotNullConstraintChange;
 37  
 import liquibase.change.core.DropPrimaryKeyChange;
 38  
 import liquibase.change.core.DropSequenceChange;
 39  
 import liquibase.change.core.DropTableChange;
 40  
 import liquibase.change.core.DropUniqueConstraintChange;
 41  
 import liquibase.change.core.DropViewChange;
 42  
 import liquibase.change.core.InsertDataChange;
 43  
 import liquibase.change.core.LoadDataChange;
 44  
 import liquibase.change.core.LoadDataColumnConfig;
 45  
 import liquibase.change.core.ModifyDataTypeChange;
 46  
 import liquibase.changelog.ChangeSet;
 47  
 import liquibase.database.Database;
 48  
 import liquibase.database.structure.Column;
 49  
 import liquibase.database.structure.ForeignKey;
 50  
 import liquibase.database.structure.Index;
 51  
 import liquibase.database.structure.PrimaryKey;
 52  
 import liquibase.database.structure.Sequence;
 53  
 import liquibase.database.structure.Table;
 54  
 import liquibase.database.structure.UniqueConstraint;
 55  
 import liquibase.database.structure.View;
 56  
 import liquibase.database.typeconversion.TypeConverter;
 57  
 import liquibase.database.typeconversion.TypeConverterFactory;
 58  
 import liquibase.exception.DatabaseException;
 59  
 import liquibase.executor.ExecutorService;
 60  
 import liquibase.logging.LogFactory;
 61  
 import liquibase.serializer.ChangeLogSerializer;
 62  
 import liquibase.serializer.ChangeLogSerializerFactory;
 63  
 import liquibase.serializer.core.xml.XMLChangeLogSerializer;
 64  
 import liquibase.snapshot.DatabaseSnapshot;
 65  
 import liquibase.statement.DatabaseFunction;
 66  
 import liquibase.statement.core.RawSqlStatement;
 67  
 import liquibase.util.ISODateFormat;
 68  
 import liquibase.util.StringUtils;
 69  
 import liquibase.util.csv.CSVWriter;
 70  
 
 71  
 public class DiffResult {
 72  
 
 73  0
     private String idRoot = String.valueOf(new Date().getTime());
 74  0
     private int changeNumber = 1;
 75  
 
 76  
     private DatabaseSnapshot referenceSnapshot;
 77  
     private DatabaseSnapshot targetSnapshot;
 78  
 
 79  
     private DiffComparison productName;
 80  
     private DiffComparison productVersion;
 81  
 
 82  0
     private SortedSet<Table> missingTables = new TreeSet<Table>();
 83  0
     private SortedSet<Table> unexpectedTables = new TreeSet<Table>();
 84  
 
 85  0
     private SortedSet<View> missingViews = new TreeSet<View>();
 86  0
     private SortedSet<View> unexpectedViews = new TreeSet<View>();
 87  0
     private SortedSet<View> changedViews = new TreeSet<View>();
 88  
 
 89  0
     private SortedSet<Column> missingColumns = new TreeSet<Column>();
 90  0
     private SortedSet<Column> unexpectedColumns = new TreeSet<Column>();
 91  0
     private SortedSet<Column> changedColumns = new TreeSet<Column>();
 92  
 
 93  0
     private SortedSet<ForeignKey> missingForeignKeys = new TreeSet<ForeignKey>();
 94  0
     private SortedSet<ForeignKey> unexpectedForeignKeys = new TreeSet<ForeignKey>();
 95  
 
 96  0
     private SortedSet<Index> missingIndexes = new TreeSet<Index>();
 97  0
     private SortedSet<Index> unexpectedIndexes = new TreeSet<Index>();
 98  
 
 99  0
     private SortedSet<PrimaryKey> missingPrimaryKeys = new TreeSet<PrimaryKey>();
 100  0
     private SortedSet<PrimaryKey> unexpectedPrimaryKeys = new TreeSet<PrimaryKey>();
 101  
 
 102  0
     private SortedSet<UniqueConstraint> missingUniqueConstraints = new TreeSet<UniqueConstraint>();
 103  0
     private SortedSet<UniqueConstraint> unexpectedUniqueConstraints = new TreeSet<UniqueConstraint>();
 104  
 
 105  0
     private SortedSet<Sequence> missingSequences = new TreeSet<Sequence>();
 106  0
     private SortedSet<Sequence> unexpectedSequences = new TreeSet<Sequence>();
 107  
 
 108  0
     private boolean diffData = false;
 109  0
     private String dataDir = null;
 110  
     private String changeSetContext;
 111  
     private String changeSetAuthor;
 112  
 
 113  0
     private ChangeLogSerializerFactory serializerFactory = ChangeLogSerializerFactory.getInstance();
 114  
 
 115  0
     public DiffResult(DatabaseSnapshot referenceDatabaseSnapshot, DatabaseSnapshot targetDatabaseSnapshot) {
 116  0
         this.referenceSnapshot = referenceDatabaseSnapshot;
 117  
 
 118  0
         if (targetDatabaseSnapshot == null) {
 119  0
             targetDatabaseSnapshot = new DatabaseSnapshot(referenceDatabaseSnapshot.getDatabase(), null);
 120  
         }
 121  0
         this.targetSnapshot = targetDatabaseSnapshot;
 122  0
     }
 123  
 
 124  
     public DiffComparison getProductName() {
 125  0
         return productName;
 126  
     }
 127  
 
 128  
     public void setProductName(DiffComparison productName) {
 129  0
         this.productName = productName;
 130  0
     }
 131  
 
 132  
     public DiffComparison getProductVersion() {
 133  0
         return productVersion;
 134  
     }
 135  
 
 136  
     public void setProductVersion(DiffComparison product) {
 137  0
         this.productVersion = product;
 138  0
     }
 139  
 
 140  
     public void addMissingTable(Table table) {
 141  0
         missingTables.add(table);
 142  0
     }
 143  
 
 144  
     public SortedSet<Table> getMissingTables() {
 145  0
         return missingTables;
 146  
     }
 147  
 
 148  
     public void addUnexpectedTable(Table table) {
 149  0
         unexpectedTables.add(table);
 150  0
     }
 151  
 
 152  
     public SortedSet<Table> getUnexpectedTables() {
 153  0
         return unexpectedTables;
 154  
     }
 155  
 
 156  
     public void addMissingView(View viewName) {
 157  0
         missingViews.add(viewName);
 158  0
     }
 159  
 
 160  
     public SortedSet<View> getMissingViews() {
 161  0
         return missingViews;
 162  
     }
 163  
 
 164  
     public void addUnexpectedView(View viewName) {
 165  0
         unexpectedViews.add(viewName);
 166  0
     }
 167  
 
 168  
     public SortedSet<View> getUnexpectedViews() {
 169  0
         return unexpectedViews;
 170  
     }
 171  
 
 172  
     public void addChangedView(View viewName) {
 173  0
         changedViews.add(viewName);
 174  0
     }
 175  
 
 176  
     public SortedSet<View> getChangedViews() {
 177  0
         return changedViews;
 178  
     }
 179  
 
 180  
     public void addMissingColumn(Column columnName) {
 181  0
         missingColumns.add(columnName);
 182  0
     }
 183  
 
 184  
     public SortedSet<Column> getMissingColumns() {
 185  0
         return missingColumns;
 186  
     }
 187  
 
 188  
     public void addUnexpectedColumn(Column columnName) {
 189  0
         unexpectedColumns.add(columnName);
 190  0
     }
 191  
 
 192  
     public SortedSet<Column> getUnexpectedColumns() {
 193  0
         return unexpectedColumns;
 194  
     }
 195  
 
 196  
     public void addChangedColumn(Column columnName) {
 197  0
         changedColumns.add(columnName);
 198  0
     }
 199  
 
 200  
     public SortedSet<Column> getChangedColumns() {
 201  0
         return changedColumns;
 202  
     }
 203  
 
 204  
     public void addMissingForeignKey(ForeignKey fkName) {
 205  0
         missingForeignKeys.add(fkName);
 206  0
     }
 207  
 
 208  
     public SortedSet<ForeignKey> getMissingForeignKeys() {
 209  0
         return missingForeignKeys;
 210  
     }
 211  
 
 212  
     public void addUnexpectedForeignKey(ForeignKey fkName) {
 213  0
         unexpectedForeignKeys.add(fkName);
 214  0
     }
 215  
 
 216  
     public SortedSet<ForeignKey> getUnexpectedForeignKeys() {
 217  0
         return unexpectedForeignKeys;
 218  
     }
 219  
 
 220  
     public void addMissingIndex(Index fkName) {
 221  0
         missingIndexes.add(fkName);
 222  0
     }
 223  
 
 224  
     public SortedSet<Index> getMissingIndexes() {
 225  0
         return missingIndexes;
 226  
     }
 227  
 
 228  
     public void addUnexpectedIndex(Index fkName) {
 229  0
         unexpectedIndexes.add(fkName);
 230  0
     }
 231  
 
 232  
     public SortedSet<Index> getUnexpectedIndexes() {
 233  0
         return unexpectedIndexes;
 234  
     }
 235  
 
 236  
     public void addMissingPrimaryKey(PrimaryKey primaryKey) {
 237  0
         missingPrimaryKeys.add(primaryKey);
 238  0
     }
 239  
 
 240  
     public SortedSet<PrimaryKey> getMissingPrimaryKeys() {
 241  0
         return missingPrimaryKeys;
 242  
     }
 243  
 
 244  
     public void addUnexpectedPrimaryKey(PrimaryKey primaryKey) {
 245  0
         unexpectedPrimaryKeys.add(primaryKey);
 246  0
     }
 247  
 
 248  
     public SortedSet<PrimaryKey> getUnexpectedPrimaryKeys() {
 249  0
         return unexpectedPrimaryKeys;
 250  
     }
 251  
 
 252  
     public void addMissingSequence(Sequence sequence) {
 253  0
         missingSequences.add(sequence);
 254  0
     }
 255  
 
 256  
     public SortedSet<Sequence> getMissingSequences() {
 257  0
         return missingSequences;
 258  
     }
 259  
 
 260  
     public void addUnexpectedSequence(Sequence sequence) {
 261  0
         unexpectedSequences.add(sequence);
 262  0
     }
 263  
 
 264  
     public SortedSet<Sequence> getUnexpectedSequences() {
 265  0
         return unexpectedSequences;
 266  
     }
 267  
 
 268  
     public void addMissingUniqueConstraint(UniqueConstraint uniqueConstraint) {
 269  0
         missingUniqueConstraints.add(uniqueConstraint);
 270  0
     }
 271  
 
 272  
     public SortedSet<UniqueConstraint> getMissingUniqueConstraints() {
 273  0
         return this.missingUniqueConstraints;
 274  
     }
 275  
 
 276  
     public void addUnexpectedUniqueConstraint(UniqueConstraint uniqueConstraint) {
 277  0
         unexpectedUniqueConstraints.add(uniqueConstraint);
 278  0
     }
 279  
 
 280  
     public SortedSet<UniqueConstraint> getUnexpectedUniqueConstraints() {
 281  0
         return unexpectedUniqueConstraints;
 282  
     }
 283  
 
 284  
     public boolean shouldDiffData() {
 285  0
         return diffData;
 286  
     }
 287  
 
 288  
     public void setDiffData(boolean diffData) {
 289  0
         this.diffData = diffData;
 290  0
     }
 291  
 
 292  
     public String getDataDir() {
 293  0
         return dataDir;
 294  
     }
 295  
 
 296  
     public void setDataDir(String dataDir) {
 297  0
         this.dataDir = dataDir;
 298  0
     }
 299  
 
 300  
     public String getChangeSetContext() {
 301  0
         return changeSetContext;
 302  
     }
 303  
 
 304  
     public void setChangeSetContext(String changeSetContext) {
 305  0
         this.changeSetContext = changeSetContext;
 306  0
     }
 307  
 
 308  
     public boolean differencesFound() throws DatabaseException, IOException {
 309  0
         boolean differencesInData = false;
 310  0
         if (shouldDiffData()) {
 311  0
             List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
 312  0
             addInsertDataChanges(changeSets, dataDir);
 313  0
             differencesInData = !changeSets.isEmpty();
 314  
         }
 315  
 
 316  0
         return getMissingColumns().size() > 0 || getMissingForeignKeys().size() > 0 || getMissingIndexes().size() > 0
 317  
                 || getMissingPrimaryKeys().size() > 0 || getMissingSequences().size() > 0
 318  
                 || getMissingTables().size() > 0 || getMissingUniqueConstraints().size() > 0
 319  
                 || getMissingViews().size() > 0 || getUnexpectedColumns().size() > 0
 320  
                 || getUnexpectedForeignKeys().size() > 0 || getUnexpectedIndexes().size() > 0
 321  
                 || getUnexpectedPrimaryKeys().size() > 0 || getUnexpectedSequences().size() > 0
 322  
                 || getUnexpectedTables().size() > 0 || getUnexpectedUniqueConstraints().size() > 0
 323  
                 || getUnexpectedViews().size() > 0 || differencesInData;
 324  
     }
 325  
 
 326  
     public void printResult(PrintStream out) throws DatabaseException {
 327  0
         out.println("Reference Database: " + referenceSnapshot.getDatabase());
 328  0
         out.println("Target Database: " + targetSnapshot.getDatabase());
 329  
 
 330  0
         printComparision("Product Name", productName, out);
 331  0
         printComparision("Product Version", productVersion, out);
 332  0
         printSetComparison("Missing Tables", getMissingTables(), out);
 333  0
         printSetComparison("Unexpected Tables", getUnexpectedTables(), out);
 334  0
         printSetComparison("Missing Views", getMissingViews(), out);
 335  0
         printSetComparison("Unexpected Views", getUnexpectedViews(), out);
 336  0
         printSetComparison("Changed Views", getChangedViews(), out);
 337  0
         printSetComparison("Missing Columns", getMissingColumns(), out);
 338  0
         printSetComparison("Unexpected Columns", getUnexpectedColumns(), out);
 339  0
         printColumnComparison(getChangedColumns(), out);
 340  0
         printSetComparison("Missing Foreign Keys", getMissingForeignKeys(), out);
 341  0
         printSetComparison("Unexpected Foreign Keys", getUnexpectedForeignKeys(), out);
 342  0
         printSetComparison("Missing Primary Keys", getMissingPrimaryKeys(), out);
 343  0
         printSetComparison("Unexpected Primary Keys", getUnexpectedPrimaryKeys(), out);
 344  0
         printSetComparison("Unexpected Unique Constraints", getUnexpectedUniqueConstraints(), out);
 345  0
         printSetComparison("Missing Unique Constraints", getMissingUniqueConstraints(), out);
 346  0
         printSetComparison("Missing Indexes", getMissingIndexes(), out);
 347  0
         printSetComparison("Unexpected Indexes", getUnexpectedIndexes(), out);
 348  0
         printSetComparison("Missing Sequences", getMissingSequences(), out);
 349  0
         printSetComparison("Unexpected Sequences", getUnexpectedSequences(), out);
 350  0
     }
 351  
 
 352  
     private void printSetComparison(String title, SortedSet<?> objects, PrintStream out) {
 353  0
         out.print(title + ": ");
 354  0
         if (objects.size() == 0) {
 355  0
             out.println("NONE");
 356  
         } else {
 357  0
             out.println();
 358  0
             for (Object object : objects) {
 359  0
                 out.println("     " + object);
 360  
             }
 361  
         }
 362  0
     }
 363  
 
 364  
     private void printColumnComparison(SortedSet<Column> changedColumns, PrintStream out) {
 365  0
         out.print("Changed Columns: ");
 366  0
         if (changedColumns.size() == 0) {
 367  0
             out.println("NONE");
 368  
         } else {
 369  0
             out.println();
 370  0
             for (Column column : changedColumns) {
 371  0
                 out.println("     " + column);
 372  0
                 Column baseColumn = referenceSnapshot.getColumn(column.getTable().getName(), column.getName());
 373  0
                 if (baseColumn != null) {
 374  0
                     if (baseColumn.isDataTypeDifferent(column)) {
 375  0
                         out.println("           from "
 376  
                                 + TypeConverterFactory.getInstance().findTypeConverter(referenceSnapshot.getDatabase())
 377  
                                         .convertToDatabaseTypeString(baseColumn, referenceSnapshot.getDatabase())
 378  
                                 + " to "
 379  
                                 + TypeConverterFactory
 380  
                                         .getInstance()
 381  
                                         .findTypeConverter(targetSnapshot.getDatabase())
 382  
                                         .convertToDatabaseTypeString(
 383  
                                                 targetSnapshot.getColumn(column.getTable().getName(), column.getName()),
 384  
                                                 targetSnapshot.getDatabase()));
 385  
                     }
 386  0
                     if (baseColumn.isNullabilityDifferent(column)) {
 387  0
                         Boolean nowNullable = targetSnapshot.getColumn(column.getTable().getName(), column.getName())
 388  
                                 .isNullable();
 389  0
                         if (nowNullable == null) {
 390  0
                             nowNullable = Boolean.TRUE;
 391  
                         }
 392  0
                         if (nowNullable) {
 393  0
                             out.println("           now nullable");
 394  
                         } else {
 395  0
                             out.println("           now not null");
 396  
                         }
 397  
                     }
 398  
                 }
 399  0
             }
 400  
         }
 401  0
     }
 402  
 
 403  
     private void printComparision(String title, DiffComparison comparison, PrintStream out) {
 404  0
         out.print(title + ":");
 405  
 
 406  0
         if (comparison == null) {
 407  0
             out.print("NULL");
 408  0
             return;
 409  
         }
 410  
 
 411  0
         if (comparison.areTheSame()) {
 412  0
             out.println(" EQUAL");
 413  
         } else {
 414  0
             out.println();
 415  0
             out.println("     Reference:   '" + comparison.getReferenceVersion() + "'");
 416  0
             out.println("     Target: '" + comparison.getTargetVersion() + "'");
 417  
         }
 418  
 
 419  0
     }
 420  
 
 421  
     public void printChangeLog(String changeLogFile, Database targetDatabase) throws ParserConfigurationException,
 422  
             IOException, DatabaseException {
 423  0
         ChangeLogSerializer changeLogSerializer = serializerFactory.getSerializer(changeLogFile);
 424  0
         this.printChangeLog(changeLogFile, targetDatabase, changeLogSerializer);
 425  0
     }
 426  
 
 427  
     public void printChangeLog(PrintStream out, Database targetDatabase) throws ParserConfigurationException,
 428  
             IOException, DatabaseException {
 429  0
         this.printChangeLog(out, targetDatabase, new XMLChangeLogSerializer());
 430  0
     }
 431  
 
 432  
     public void printChangeLog(String changeLogFile, Database targetDatabase, ChangeLogSerializer changeLogSerializer)
 433  
             throws ParserConfigurationException, IOException, DatabaseException {
 434  0
         File file = new File(changeLogFile);
 435  0
         if (!file.exists()) {
 436  0
             LogFactory.getLogger().info(file + " does not exist, creating");
 437  0
             FileOutputStream stream = new FileOutputStream(file);
 438  0
             printChangeLog(new PrintStream(stream), targetDatabase, changeLogSerializer);
 439  0
             stream.close();
 440  0
         } else {
 441  0
             LogFactory.getLogger().info(file + " exists, appending");
 442  0
             ByteArrayOutputStream out = new ByteArrayOutputStream();
 443  0
             printChangeLog(new PrintStream(out), targetDatabase, changeLogSerializer);
 444  
 
 445  0
             String xml = new String(out.toByteArray());
 446  0
             xml = xml.replaceFirst("(?ms).*<databaseChangeLog[^>]*>", "");
 447  0
             xml = xml.replaceFirst("</databaseChangeLog>", "");
 448  0
             xml = xml.trim();
 449  0
             if ("".equals(xml)) {
 450  0
                 LogFactory.getLogger().info("No changes found, nothing to do");
 451  0
                 return;
 452  
             }
 453  
 
 454  0
             String lineSeparator = System.getProperty("line.separator");
 455  0
             BufferedReader fileReader = new BufferedReader(new FileReader(file));
 456  
             String line;
 457  0
             long offset = 0;
 458  0
             while ((line = fileReader.readLine()) != null) {
 459  0
                 int index = line.indexOf("</databaseChangeLog>");
 460  0
                 if (index >= 0) {
 461  0
                     offset += index;
 462  
                 } else {
 463  0
                     offset += line.getBytes().length;
 464  0
                     offset += lineSeparator.getBytes().length;
 465  
                 }
 466  0
             }
 467  0
             fileReader.close();
 468  
 
 469  0
             fileReader = new BufferedReader(new FileReader(file));
 470  0
             fileReader.skip(offset);
 471  
 
 472  0
             fileReader.close();
 473  
 
 474  
             // System.out.println("resulting XML: " + xml.trim());
 475  
 
 476  0
             RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
 477  0
             randomAccessFile.seek(offset);
 478  0
             randomAccessFile.writeBytes("    ");
 479  0
             randomAccessFile.write(xml.getBytes());
 480  0
             randomAccessFile.writeBytes(lineSeparator);
 481  0
             randomAccessFile.writeBytes("</databaseChangeLog>" + lineSeparator);
 482  0
             randomAccessFile.close();
 483  
 
 484  
             // BufferedWriter fileWriter = new BufferedWriter(new
 485  
             // FileWriter(file));
 486  
             // fileWriter.append(xml);
 487  
             // fileWriter.close();
 488  
         }
 489  0
     }
 490  
 
 491  
     /**
 492  
      * Prints changeLog that would bring the target database to be the same as the reference database
 493  
      */
 494  
     public void printChangeLog(PrintStream out, Database targetDatabase, ChangeLogSerializer changeLogSerializer)
 495  
             throws ParserConfigurationException, IOException, DatabaseException {
 496  0
         List<ChangeSet> changeSets = new ArrayList<ChangeSet>();
 497  0
         addMissingTableChanges(changeSets, targetDatabase);
 498  0
         addMissingColumnChanges(changeSets, targetDatabase);
 499  0
         addChangedColumnChanges(changeSets);
 500  0
         addMissingPrimaryKeyChanges(changeSets);
 501  0
         addUnexpectedPrimaryKeyChanges(changeSets);
 502  0
         addUnexpectedForeignKeyChanges(changeSets);
 503  0
         addMissingUniqueConstraintChanges(changeSets);
 504  0
         addMissingIndexChanges(changeSets);
 505  0
         addUnexpectedUniqueConstraintChanges(changeSets);
 506  
 
 507  0
         if (diffData) {
 508  0
             addInsertDataChanges(changeSets, dataDir);
 509  
         }
 510  
 
 511  0
         addMissingForeignKeyChanges(changeSets);
 512  0
         addUnexpectedIndexChanges(changeSets);
 513  0
         addUnexpectedColumnChanges(changeSets);
 514  0
         addMissingSequenceChanges(changeSets);
 515  0
         addUnexpectedSequenceChanges(changeSets);
 516  0
         addMissingViewChanges(changeSets);
 517  0
         addUnexpectedViewChanges(changeSets);
 518  0
         addChangedViewChanges(changeSets);
 519  0
         addUnexpectedTableChanges(changeSets);
 520  
 
 521  0
         changeLogSerializer.write(changeSets, out);
 522  
 
 523  0
         out.flush();
 524  0
     }
 525  
 
 526  
     private ChangeSet generateChangeSet(Change change) {
 527  0
         ChangeSet changeSet = generateChangeSet();
 528  0
         changeSet.addChange(change);
 529  
 
 530  0
         return changeSet;
 531  
     }
 532  
 
 533  
     private ChangeSet generateChangeSet() {
 534  0
         return new ChangeSet(generateId(), getChangeSetAuthor(), false, false, null, getChangeSetContext(), null);
 535  
     }
 536  
 
 537  
     private String getChangeSetAuthor() {
 538  0
         if (changeSetAuthor != null) {
 539  0
             return changeSetAuthor;
 540  
         }
 541  0
         String author = System.getProperty("user.name");
 542  0
         if (StringUtils.trimToNull(author) == null) {
 543  0
             return "diff-generated";
 544  
         } else {
 545  0
             return author + " (generated)";
 546  
         }
 547  
     }
 548  
 
 549  
     public void setChangeSetAuthor(String changeSetAuthor) {
 550  0
         this.changeSetAuthor = changeSetAuthor;
 551  0
     }
 552  
 
 553  
     public void setIdRoot(String idRoot) {
 554  0
         this.idRoot = idRoot;
 555  0
     }
 556  
 
 557  
     protected String generateId() {
 558  0
         return idRoot + "-" + changeNumber++;
 559  
     }
 560  
 
 561  
     private void addUnexpectedIndexChanges(List<ChangeSet> changes) {
 562  0
         for (Index index : getUnexpectedIndexes()) {
 563  
 
 564  0
             if (index.getAssociatedWith().contains(Index.MARK_PRIMARY_KEY)
 565  
                     || index.getAssociatedWith().contains(Index.MARK_FOREIGN_KEY)
 566  
                     || index.getAssociatedWith().contains(Index.MARK_UNIQUE_CONSTRAINT)) {
 567  0
                 continue;
 568  
             }
 569  
 
 570  0
             DropIndexChange change = new DropIndexChange();
 571  0
             change.setTableName(index.getTable().getName());
 572  0
             change.setSchemaName(index.getTable().getSchema());
 573  0
             change.setIndexName(index.getName());
 574  0
             change.setAssociatedWith(index.getAssociatedWithAsString());
 575  
 
 576  0
             changes.add(generateChangeSet(change));
 577  0
         }
 578  0
     }
 579  
 
 580  
     private void addMissingIndexChanges(List<ChangeSet> changes) {
 581  0
         for (Index index : getMissingIndexes()) {
 582  
 
 583  0
             CreateIndexChange change = new CreateIndexChange();
 584  0
             change.setTableName(index.getTable().getName());
 585  0
             change.setTablespace(index.getTablespace());
 586  0
             change.setSchemaName(index.getTable().getSchema());
 587  0
             change.setIndexName(index.getName());
 588  0
             change.setUnique(index.isUnique());
 589  0
             change.setAssociatedWith(index.getAssociatedWithAsString());
 590  
 
 591  0
             if (index.getAssociatedWith().contains(Index.MARK_PRIMARY_KEY)
 592  
                     || index.getAssociatedWith().contains(Index.MARK_FOREIGN_KEY)
 593  
                     || index.getAssociatedWith().contains(Index.MARK_UNIQUE_CONSTRAINT)) {
 594  0
                 continue;
 595  
             }
 596  
 
 597  0
             for (String columnName : index.getColumns()) {
 598  0
                 ColumnConfig column = new ColumnConfig();
 599  0
                 column.setName(columnName);
 600  0
                 change.addColumn(column);
 601  0
             }
 602  0
             changes.add(generateChangeSet(change));
 603  0
         }
 604  0
     }
 605  
 
 606  
     private void addUnexpectedPrimaryKeyChanges(List<ChangeSet> changes) {
 607  0
         for (PrimaryKey pk : getUnexpectedPrimaryKeys()) {
 608  
 
 609  0
             if (!getUnexpectedTables().contains(pk.getTable())) {
 610  0
                 DropPrimaryKeyChange change = new DropPrimaryKeyChange();
 611  0
                 change.setTableName(pk.getTable().getName());
 612  0
                 change.setSchemaName(pk.getTable().getSchema());
 613  0
                 change.setConstraintName(pk.getName());
 614  
 
 615  0
                 changes.add(generateChangeSet(change));
 616  0
             }
 617  
         }
 618  0
     }
 619  
 
 620  
     private void addMissingPrimaryKeyChanges(List<ChangeSet> changes) {
 621  0
         for (PrimaryKey pk : getMissingPrimaryKeys()) {
 622  
 
 623  0
             AddPrimaryKeyChange change = new AddPrimaryKeyChange();
 624  0
             change.setTableName(pk.getTable().getName());
 625  0
             change.setSchemaName(pk.getTable().getSchema());
 626  0
             change.setConstraintName(pk.getName());
 627  0
             change.setColumnNames(pk.getColumnNames());
 628  0
             change.setTablespace(pk.getTablespace());
 629  
 
 630  0
             changes.add(generateChangeSet(change));
 631  0
         }
 632  0
     }
 633  
 
 634  
     private void addUnexpectedUniqueConstraintChanges(List<ChangeSet> changes) {
 635  0
         for (UniqueConstraint uc : getUnexpectedUniqueConstraints()) {
 636  
             // Need check for nulls here due to NullPointerException using Postgres
 637  0
             if (null != uc) {
 638  0
                 if (null != uc.getTable()) {
 639  0
                     DropUniqueConstraintChange change = new DropUniqueConstraintChange();
 640  0
                     change.setTableName(uc.getTable().getName());
 641  0
                     change.setSchemaName(uc.getTable().getSchema());
 642  0
                     change.setConstraintName(uc.getName());
 643  
 
 644  0
                     changes.add(generateChangeSet(change));
 645  0
                 }
 646  
             }
 647  
         }
 648  0
     }
 649  
 
 650  
     private void addMissingUniqueConstraintChanges(List<ChangeSet> changes) {
 651  0
         for (UniqueConstraint uc : getMissingUniqueConstraints()) {
 652  
             // Need check for nulls here due to NullPointerException using Postgres
 653  0
             if (null != uc)
 654  0
                 if (null != uc.getTable()) {
 655  0
                     AddUniqueConstraintChange change = new AddUniqueConstraintChange();
 656  0
                     change.setTableName(uc.getTable().getName());
 657  0
                     change.setTablespace(uc.getTablespace());
 658  0
                     change.setSchemaName(uc.getTable().getSchema());
 659  0
                     change.setConstraintName(uc.getName());
 660  0
                     change.setColumnNames(uc.getColumnNames());
 661  0
                     change.setDeferrable(uc.isDeferrable());
 662  0
                     change.setInitiallyDeferred(uc.isInitiallyDeferred());
 663  0
                     change.setDisabled(uc.isDisabled());
 664  0
                     changes.add(generateChangeSet(change));
 665  0
                 }
 666  
         }
 667  0
     }
 668  
 
 669  
     private void addUnexpectedForeignKeyChanges(List<ChangeSet> changes) {
 670  0
         for (ForeignKey fk : getUnexpectedForeignKeys()) {
 671  
 
 672  0
             DropForeignKeyConstraintChange change = new DropForeignKeyConstraintChange();
 673  0
             change.setConstraintName(fk.getName());
 674  0
             change.setBaseTableName(fk.getForeignKeyTable().getName());
 675  0
             change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema());
 676  
 
 677  0
             changes.add(generateChangeSet(change));
 678  0
         }
 679  0
     }
 680  
 
 681  
     private void addMissingForeignKeyChanges(List<ChangeSet> changes) {
 682  0
         for (ForeignKey fk : getMissingForeignKeys()) {
 683  
 
 684  0
             AddForeignKeyConstraintChange change = new AddForeignKeyConstraintChange();
 685  0
             change.setConstraintName(fk.getName());
 686  
 
 687  0
             change.setReferencedTableName(fk.getPrimaryKeyTable().getName());
 688  0
             change.setReferencedTableSchemaName(fk.getPrimaryKeyTable().getSchema());
 689  0
             change.setReferencedColumnNames(fk.getPrimaryKeyColumns());
 690  
 
 691  0
             change.setBaseTableName(fk.getForeignKeyTable().getName());
 692  0
             change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema());
 693  0
             change.setBaseColumnNames(fk.getForeignKeyColumns());
 694  
 
 695  0
             change.setDeferrable(fk.isDeferrable());
 696  0
             change.setInitiallyDeferred(fk.isInitiallyDeferred());
 697  0
             change.setOnUpdate(fk.getUpdateRule());
 698  0
             change.setOnDelete(fk.getDeleteRule());
 699  
 
 700  0
             change.setReferencesUniqueColumn(fk.getReferencesUniqueColumn());
 701  
 
 702  0
             changes.add(generateChangeSet(change));
 703  0
         }
 704  0
     }
 705  
 
 706  
     private void addUnexpectedSequenceChanges(List<ChangeSet> changes) {
 707  0
         for (Sequence sequence : getUnexpectedSequences()) {
 708  
 
 709  0
             DropSequenceChange change = new DropSequenceChange();
 710  0
             change.setSequenceName(sequence.getName());
 711  0
             change.setSchemaName(sequence.getSchema());
 712  
 
 713  0
             changes.add(generateChangeSet(change));
 714  0
         }
 715  0
     }
 716  
 
 717  
     private void addMissingSequenceChanges(List<ChangeSet> changes) {
 718  0
         for (Sequence sequence : getMissingSequences()) {
 719  
 
 720  0
             CreateSequenceChange change = new CreateSequenceChange();
 721  0
             change.setSequenceName(sequence.getName());
 722  0
             change.setSchemaName(sequence.getSchema());
 723  
 
 724  0
             changes.add(generateChangeSet(change));
 725  0
         }
 726  0
     }
 727  
 
 728  
     private void addUnexpectedColumnChanges(List<ChangeSet> changes) {
 729  0
         for (Column column : getUnexpectedColumns()) {
 730  0
             if (!shouldModifyColumn(column)) {
 731  0
                 continue;
 732  
             }
 733  
 
 734  0
             DropColumnChange change = new DropColumnChange();
 735  0
             change.setTableName(column.getTable().getName());
 736  0
             change.setSchemaName(column.getTable().getSchema());
 737  0
             change.setColumnName(column.getName());
 738  
 
 739  0
             changes.add(generateChangeSet(change));
 740  0
         }
 741  0
     }
 742  
 
 743  
     private void addMissingViewChanges(List<ChangeSet> changes) {
 744  0
         for (View view : getMissingViews()) {
 745  
 
 746  0
             CreateViewChange change = new CreateViewChange();
 747  0
             change.setViewName(view.getName());
 748  0
             change.setSchemaName(view.getSchema());
 749  0
             String selectQuery = view.getDefinition();
 750  0
             if (selectQuery == null) {
 751  0
                 selectQuery = "COULD NOT DETERMINE VIEW QUERY";
 752  
             }
 753  0
             change.setSelectQuery(selectQuery);
 754  
 
 755  0
             changes.add(generateChangeSet(change));
 756  0
         }
 757  0
     }
 758  
 
 759  
     private void addChangedViewChanges(List<ChangeSet> changes) {
 760  0
         for (View view : getChangedViews()) {
 761  
 
 762  0
             CreateViewChange change = new CreateViewChange();
 763  0
             change.setViewName(view.getName());
 764  0
             change.setSchemaName(view.getSchema());
 765  0
             String selectQuery = view.getDefinition();
 766  0
             if (selectQuery == null) {
 767  0
                 selectQuery = "COULD NOT DETERMINE VIEW QUERY";
 768  
             }
 769  0
             change.setSelectQuery(selectQuery);
 770  0
             change.setReplaceIfExists(true);
 771  
 
 772  0
             changes.add(generateChangeSet(change));
 773  0
         }
 774  0
     }
 775  
 
 776  
     private void addChangedColumnChanges(List<ChangeSet> changes) {
 777  0
         for (Column column : getChangedColumns()) {
 778  0
             if (!shouldModifyColumn(column)) {
 779  0
                 continue;
 780  
             }
 781  
 
 782  0
             TypeConverter targetTypeConverter = TypeConverterFactory.getInstance().findTypeConverter(
 783  
                     targetSnapshot.getDatabase());
 784  0
             boolean foundDifference = false;
 785  0
             Column referenceColumn = referenceSnapshot.getColumn(column.getTable().getName(), column.getName());
 786  0
             if (column.isDataTypeDifferent(referenceColumn)) {
 787  0
                 ModifyDataTypeChange change = new ModifyDataTypeChange();
 788  0
                 change.setTableName(column.getTable().getName());
 789  0
                 change.setSchemaName(column.getTable().getSchema());
 790  0
                 change.setColumnName(column.getName());
 791  0
                 change.setNewDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn,
 792  
                         targetSnapshot.getDatabase()));
 793  0
                 changes.add(generateChangeSet(change));
 794  0
                 foundDifference = true;
 795  
             }
 796  0
             if (column.isNullabilityDifferent(referenceColumn)) {
 797  0
                 if (referenceColumn.isNullable() == null || referenceColumn.isNullable()) {
 798  0
                     DropNotNullConstraintChange change = new DropNotNullConstraintChange();
 799  0
                     change.setTableName(column.getTable().getName());
 800  0
                     change.setSchemaName(column.getTable().getSchema());
 801  0
                     change.setColumnName(column.getName());
 802  0
                     change.setColumnDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn,
 803  
                             targetSnapshot.getDatabase()));
 804  
 
 805  0
                     changes.add(generateChangeSet(change));
 806  0
                     foundDifference = true;
 807  0
                 } else {
 808  0
                     AddNotNullConstraintChange change = new AddNotNullConstraintChange();
 809  0
                     change.setTableName(column.getTable().getName());
 810  0
                     change.setSchemaName(column.getTable().getSchema());
 811  0
                     change.setColumnName(column.getName());
 812  0
                     change.setColumnDataType(targetTypeConverter.convertToDatabaseTypeString(referenceColumn,
 813  
                             targetSnapshot.getDatabase()));
 814  
 
 815  0
                     Object defaultValue = column.getDefaultValue();
 816  
                     String defaultValueString;
 817  0
                     if (defaultValue != null) {
 818  0
                         defaultValueString = targetTypeConverter.getDataType(defaultValue).convertObjectToString(
 819  
                                 defaultValue, targetSnapshot.getDatabase());
 820  
 
 821  0
                         if (defaultValueString != null) {
 822  0
                             change.setDefaultNullValue(defaultValueString);
 823  
                         }
 824  
                     }
 825  
 
 826  0
                     changes.add(generateChangeSet(change));
 827  0
                     foundDifference = true;
 828  
                 }
 829  
 
 830  
             }
 831  0
             if (!foundDifference) {
 832  0
                 throw new RuntimeException("Unknown difference");
 833  
             }
 834  0
         }
 835  0
     }
 836  
 
 837  
     private boolean shouldModifyColumn(Column column) {
 838  0
         return column.getView() == null
 839  
                 && !referenceSnapshot.getDatabase().isLiquibaseTable(column.getTable().getName());
 840  
 
 841  
     }
 842  
 
 843  
     private void addUnexpectedViewChanges(List<ChangeSet> changes) {
 844  0
         for (View view : getUnexpectedViews()) {
 845  
 
 846  0
             DropViewChange change = new DropViewChange();
 847  0
             change.setViewName(view.getName());
 848  0
             change.setSchemaName(view.getSchema());
 849  
 
 850  0
             changes.add(generateChangeSet(change));
 851  0
         }
 852  0
     }
 853  
 
 854  
     private void addMissingColumnChanges(List<ChangeSet> changes, Database database) {
 855  0
         for (Column column : getMissingColumns()) {
 856  0
             if (!shouldModifyColumn(column)) {
 857  0
                 continue;
 858  
             }
 859  
 
 860  0
             AddColumnChange change = new AddColumnChange();
 861  0
             change.setTableName(column.getTable().getName());
 862  0
             change.setSchemaName(column.getTable().getSchema());
 863  
 
 864  0
             ColumnConfig columnConfig = new ColumnConfig();
 865  0
             columnConfig.setName(column.getName());
 866  
 
 867  0
             String dataType = TypeConverterFactory.getInstance().findTypeConverter(database)
 868  
                     .convertToDatabaseTypeString(column, database);
 869  
 
 870  0
             columnConfig.setType(dataType);
 871  
 
 872  0
             Object defaultValue = column.getDefaultValue();
 873  0
             if (defaultValue != null) {
 874  0
                 String defaultValueString = TypeConverterFactory.getInstance().findTypeConverter(database)
 875  
                         .getDataType(defaultValue).convertObjectToString(defaultValue, database);
 876  0
                 if (defaultValueString != null) {
 877  0
                     defaultValueString = defaultValueString.replaceFirst("'", "").replaceAll("'$", "");
 878  
                 }
 879  0
                 columnConfig.setDefaultValue(defaultValueString);
 880  
             }
 881  
 
 882  0
             if (column.getRemarks() != null) {
 883  0
                 columnConfig.setRemarks(column.getRemarks());
 884  
             }
 885  0
             ConstraintsConfig constraintsConfig = columnConfig.getConstraints();
 886  0
             if (column.isNullable() != null && !column.isNullable()) {
 887  0
                 if (constraintsConfig == null) {
 888  0
                     constraintsConfig = new ConstraintsConfig();
 889  
                 }
 890  0
                 constraintsConfig.setNullable(false);
 891  
             }
 892  0
             if (column.isUnique()) {
 893  0
                 if (constraintsConfig == null) {
 894  0
                     constraintsConfig = new ConstraintsConfig();
 895  
                 }
 896  0
                 constraintsConfig.setUnique(true);
 897  
             }
 898  0
             if (constraintsConfig != null) {
 899  0
                 columnConfig.setConstraints(constraintsConfig);
 900  
             }
 901  
 
 902  0
             change.addColumn(columnConfig);
 903  
 
 904  0
             changes.add(generateChangeSet(change));
 905  0
         }
 906  0
     }
 907  
 
 908  
     private void addMissingTableChanges(List<ChangeSet> changes, Database database) {
 909  0
         for (Table missingTable : getMissingTables()) {
 910  0
             if (referenceSnapshot.getDatabase().isLiquibaseTable(missingTable.getName())) {
 911  0
                 continue;
 912  
             }
 913  
 
 914  0
             CreateTableChange change = new CreateTableChange();
 915  0
             change.setTableName(missingTable.getName());
 916  0
             change.setSchemaName(missingTable.getSchema());
 917  0
             if (missingTable.getRemarks() != null) {
 918  0
                 change.setRemarks(missingTable.getRemarks());
 919  
             }
 920  
 
 921  0
             for (Column column : missingTable.getColumns()) {
 922  0
                 ColumnConfig columnConfig = new ColumnConfig();
 923  0
                 columnConfig.setName(column.getName());
 924  0
                 columnConfig.setType(TypeConverterFactory.getInstance().findTypeConverter(database)
 925  
                         .convertToDatabaseTypeString(column, database));
 926  
 
 927  0
                 ConstraintsConfig constraintsConfig = null;
 928  0
                 if (column.isPrimaryKey()) {
 929  0
                     PrimaryKey primaryKey = null;
 930  0
                     for (PrimaryKey pk : getMissingPrimaryKeys()) {
 931  0
                         if (pk.getTable().getName().equalsIgnoreCase(missingTable.getName())) {
 932  0
                             primaryKey = pk;
 933  
                         }
 934  
                     }
 935  
 
 936  0
                     if (primaryKey == null || primaryKey.getColumnNamesAsList().size() == 1) {
 937  0
                         constraintsConfig = new ConstraintsConfig();
 938  0
                         constraintsConfig.setPrimaryKey(true);
 939  0
                         constraintsConfig.setPrimaryKeyTablespace(column.getTablespace());
 940  
 
 941  0
                         if (primaryKey != null) {
 942  0
                             constraintsConfig.setPrimaryKeyName(primaryKey.getName());
 943  0
                             getMissingPrimaryKeys().remove(primaryKey);
 944  
                         }
 945  
                     }
 946  
                 }
 947  
 
 948  0
                 if (column.isAutoIncrement()) {
 949  0
                     columnConfig.setAutoIncrement(true);
 950  
                 }
 951  
 
 952  0
                 if (column.isNullable() != null && !column.isNullable()) {
 953  0
                     if (constraintsConfig == null) {
 954  0
                         constraintsConfig = new ConstraintsConfig();
 955  
                     }
 956  
 
 957  0
                     constraintsConfig.setNullable(false);
 958  
                 }
 959  0
                 if (column.isUnique()) {
 960  0
                     if (constraintsConfig == null) {
 961  0
                         constraintsConfig = new ConstraintsConfig();
 962  
                     }
 963  0
                     constraintsConfig.setUnique(true);
 964  
                 }
 965  0
                 if (constraintsConfig != null) {
 966  0
                     columnConfig.setConstraints(constraintsConfig);
 967  
                 }
 968  
 
 969  0
                 Object defaultValue = column.getDefaultValue();
 970  0
                 if (defaultValue == null) {
 971  
                     // do nothing
 972  0
                 } else if (column.isAutoIncrement()) {
 973  
                     // do nothing
 974  0
                 } else if (defaultValue instanceof Date) {
 975  0
                     columnConfig.setDefaultValueDate((Date) defaultValue);
 976  0
                 } else if (defaultValue instanceof Boolean) {
 977  0
                     columnConfig.setDefaultValueBoolean(((Boolean) defaultValue));
 978  0
                 } else if (defaultValue instanceof Number) {
 979  0
                     columnConfig.setDefaultValueNumeric(((Number) defaultValue));
 980  0
                 } else if (defaultValue instanceof DatabaseFunction) {
 981  0
                     columnConfig.setDefaultValueComputed((DatabaseFunction) defaultValue);
 982  
                 } else {
 983  0
                     columnConfig.setDefaultValue(defaultValue.toString());
 984  
                 }
 985  
 
 986  0
                 if (column.getRemarks() != null) {
 987  0
                     columnConfig.setRemarks(column.getRemarks());
 988  
                 }
 989  
 
 990  0
                 change.addColumn(columnConfig);
 991  0
             }
 992  
 
 993  0
             changes.add(generateChangeSet(change));
 994  0
         }
 995  0
     }
 996  
 
 997  
     private void addUnexpectedTableChanges(List<ChangeSet> changes) {
 998  0
         for (Table unexpectedTable : getUnexpectedTables()) {
 999  0
             DropTableChange change = new DropTableChange();
 1000  0
             change.setTableName(unexpectedTable.getName());
 1001  0
             change.setSchemaName(unexpectedTable.getSchema());
 1002  
 
 1003  0
             changes.add(generateChangeSet(change));
 1004  0
         }
 1005  0
     }
 1006  
 
 1007  
     private void addInsertDataChanges(List<ChangeSet> changeSets, String dataDir) throws DatabaseException, IOException {
 1008  
         try {
 1009  0
             String schema = referenceSnapshot.getSchema();
 1010  0
             for (Table table : referenceSnapshot.getTables()) {
 1011  0
                 List<Change> changes = new ArrayList<Change>();
 1012  0
                 List<Map> rs = ExecutorService
 1013  
                         .getInstance()
 1014  
                         .getExecutor(referenceSnapshot.getDatabase())
 1015  
                         .queryForList(
 1016  
                                 new RawSqlStatement("SELECT * FROM "
 1017  
                                         + referenceSnapshot.getDatabase().escapeTableName(schema, table.getName())));
 1018  
 
 1019  0
                 if (rs.size() == 0) {
 1020  0
                     continue;
 1021  
                 }
 1022  
 
 1023  0
                 List<String> columnNames = new ArrayList<String>();
 1024  0
                 for (Column column : table.getColumns()) {
 1025  0
                     columnNames.add(column.getName());
 1026  
                 }
 1027  
 
 1028  
                 // if dataDir is not null, print out a csv file and use loadData
 1029  
                 // tag
 1030  0
                 if (dataDir != null) {
 1031  0
                     String fileName = table.getName().toLowerCase() + ".csv";
 1032  0
                     if (dataDir != null) {
 1033  0
                         fileName = dataDir + "/" + fileName;
 1034  
                     }
 1035  
 
 1036  0
                     File parentDir = new File(dataDir);
 1037  0
                     if (!parentDir.exists()) {
 1038  0
                         parentDir.mkdirs();
 1039  
                     }
 1040  0
                     if (!parentDir.isDirectory()) {
 1041  0
                         throw new RuntimeException(parentDir + " is not a directory");
 1042  
                     }
 1043  
 
 1044  0
                     CSVWriter outputFile = new CSVWriter(new FileWriter(fileName));
 1045  0
                     String[] dataTypes = new String[columnNames.size()];
 1046  0
                     String[] line = new String[columnNames.size()];
 1047  0
                     for (int i = 0; i < columnNames.size(); i++) {
 1048  0
                         line[i] = columnNames.get(i);
 1049  
                     }
 1050  0
                     outputFile.writeNext(line);
 1051  
 
 1052  0
                     for (Map row : rs) {
 1053  0
                         line = new String[columnNames.size()];
 1054  
 
 1055  0
                         for (int i = 0; i < columnNames.size(); i++) {
 1056  0
                             Object value = row.get(columnNames.get(i).toUpperCase());
 1057  0
                             if (dataTypes[i] == null && value != null) {
 1058  0
                                 if (value instanceof Number) {
 1059  0
                                     dataTypes[i] = "NUMERIC";
 1060  0
                                 } else if (value instanceof Boolean) {
 1061  0
                                     dataTypes[i] = "BOOLEAN";
 1062  0
                                 } else if (value instanceof Date) {
 1063  0
                                     dataTypes[i] = "DATE";
 1064  
                                 } else {
 1065  0
                                     dataTypes[i] = "STRING";
 1066  
                                 }
 1067  
                             }
 1068  0
                             if (value == null) {
 1069  0
                                 line[i] = "NULL";
 1070  
                             } else {
 1071  0
                                 if (value instanceof Date) {
 1072  0
                                     line[i] = new ISODateFormat().format(((Date) value));
 1073  
                                 } else {
 1074  0
                                     line[i] = value.toString();
 1075  
                                 }
 1076  
                             }
 1077  
                         }
 1078  0
                         outputFile.writeNext(line);
 1079  
                     }
 1080  0
                     outputFile.flush();
 1081  0
                     outputFile.close();
 1082  
 
 1083  0
                     LoadDataChange change = new LoadDataChange();
 1084  0
                     change.setFile(fileName);
 1085  0
                     change.setEncoding("UTF-8");
 1086  0
                     change.setSchemaName(schema);
 1087  0
                     change.setTableName(table.getName());
 1088  
 
 1089  0
                     for (int i = 0; i < columnNames.size(); i++) {
 1090  0
                         String colName = columnNames.get(i);
 1091  0
                         LoadDataColumnConfig columnConfig = new LoadDataColumnConfig();
 1092  0
                         columnConfig.setHeader(colName);
 1093  0
                         columnConfig.setName(colName);
 1094  0
                         columnConfig.setType(dataTypes[i]);
 1095  
 
 1096  0
                         change.addColumn(columnConfig);
 1097  
                     }
 1098  
 
 1099  0
                     changes.add(change);
 1100  0
                 } else { // if dataDir is null, build and use insert tags
 1101  0
                     for (Map row : rs) {
 1102  0
                         InsertDataChange change = new InsertDataChange();
 1103  0
                         change.setSchemaName(schema);
 1104  0
                         change.setTableName(table.getName());
 1105  
 
 1106  
                         // loop over all columns for this row
 1107  0
                         for (int i = 0; i < columnNames.size(); i++) {
 1108  0
                             ColumnConfig column = new ColumnConfig();
 1109  0
                             column.setName(columnNames.get(i));
 1110  
 
 1111  0
                             Object value = row.get(columnNames.get(i).toUpperCase());
 1112  0
                             if (value == null) {
 1113  0
                                 column.setValue(null);
 1114  0
                             } else if (value instanceof Number) {
 1115  0
                                 column.setValueNumeric((Number) value);
 1116  0
                             } else if (value instanceof Boolean) {
 1117  0
                                 column.setValueBoolean((Boolean) value);
 1118  0
                             } else if (value instanceof Date) {
 1119  0
                                 column.setValueDate((Date) value);
 1120  
                             } else { // string
 1121  0
                                 column.setValue(value.toString().replace("\\", "\\\\"));
 1122  
                             }
 1123  
 
 1124  0
                             change.addColumn(column);
 1125  
 
 1126  
                         }
 1127  
 
 1128  
                         // for each row, add a new change
 1129  
                         // (there will be one group per table)
 1130  0
                         changes.add(change);
 1131  0
                     }
 1132  
 
 1133  
                 }
 1134  0
                 if (changes.size() > 0) {
 1135  0
                     ChangeSet changeSet = generateChangeSet();
 1136  0
                     for (Change change : changes) {
 1137  0
                         changeSet.addChange(change);
 1138  
                     }
 1139  0
                     changeSets.add(changeSet);
 1140  
                 }
 1141  0
             }
 1142  
 
 1143  0
         } catch (Exception e) {
 1144  0
             throw new RuntimeException(e);
 1145  0
         }
 1146  0
     }
 1147  
 }