@Override public Change[] fixChanged( DatabaseObject changedObject, ObjectDifferences differences, DiffOutputControl control, Database referenceDatabase, final Database comparisonDatabase, ChangeGeneratorChain chain) { Table table = (Table) changedObject; Difference changedRemarks = differences.getDifference("remarks"); if (changedRemarks != null) { SetTableRemarksChange change = new SetTableRemarksChange(); if (control.getIncludeCatalog()) { change.setCatalogName(table.getSchema().getCatalogName()); } if (control.getIncludeSchema()) { change.setSchemaName(table.getSchema().getName()); } change.setTableName(table.getName()); change.setRemarks(table.getRemarks()); return new Change[] {change}; } return null; }
protected Table readTable(CachedRow tableMetadataResultSet, Database database) throws SQLException, DatabaseException { String rawTableName = tableMetadataResultSet.getString("TABLE_NAME"); String rawSchemaName = StringUtils.trimToNull(tableMetadataResultSet.getString("TABLE_SCHEM")); String rawCatalogName = StringUtils.trimToNull(tableMetadataResultSet.getString("TABLE_CAT")); String remarks = StringUtils.trimToNull(tableMetadataResultSet.getString("REMARKS")); if (remarks != null) { remarks = remarks.replace("''", "'"); // come back escaped sometimes } Table table = new Table().setName(cleanNameFromDatabase(rawTableName, database)); table.setRemarks(remarks); CatalogAndSchema schemaFromJdbcInfo = ((AbstractJdbcDatabase) database).getSchemaFromJdbcInfo(rawCatalogName, rawSchemaName); table.setSchema( new Schema(schemaFromJdbcInfo.getCatalogName(), schemaFromJdbcInfo.getSchemaName())); return table; }
public static List<SqlStatement> getAlterTableStatements( AlterTableVisitor alterTableVisitor, Database database, String catalogName, String schemaName, String tableName) throws DatabaseException { DatabaseSnapshot snapshot = null; // todo List<SqlStatement> statements = new ArrayList<SqlStatement>(); Table table = null; try { table = SnapshotGeneratorFactory.getInstance() .createSnapshot( (Table) new Table().setName(tableName).setSchema(new Schema(new Catalog(null), null)), database); } catch (InvalidExampleException e) { throw new UnexpectedLiquibaseException(e); } List<ColumnConfig> createColumns = new Vector<ColumnConfig>(); List<ColumnConfig> copyColumns = new Vector<ColumnConfig>(); if (table != null) { for (Column column : table.getColumns()) { ColumnConfig new_column = new ColumnConfig(column); if (alterTableVisitor.createThisColumn(new_column)) { createColumns.add(new_column); } ColumnConfig copy_column = new ColumnConfig(column); if (alterTableVisitor.copyThisColumn(copy_column)) { copyColumns.add(copy_column); } } } for (ColumnConfig column : alterTableVisitor.getColumnsToAdd()) { if (alterTableVisitor.createThisColumn(column)) { createColumns.add(column); } if (alterTableVisitor.copyThisColumn(column)) { copyColumns.add(column); } } List<Index> newIndices = new Vector<Index>(); for (Index index : new ArrayList< Index>()) { // todo SnapshotGeneratorFactory.getInstance().getGenerator(Index.class, // database).get(new Schema(new Catalog(null), schemaName), database)) { if (index.getTable().getName().equalsIgnoreCase(tableName)) { if (alterTableVisitor.createThisIndex(index)) { newIndices.add(index); } } } // rename table String temp_table_name = tableName + "_temporary"; statements.add(new RenameTableStatement(catalogName, schemaName, tableName, temp_table_name)); // create temporary table CreateTableChange ct_change_tmp = new CreateTableChange(); ct_change_tmp.setSchemaName(schemaName); ct_change_tmp.setTableName(tableName); for (ColumnConfig column : createColumns) { ct_change_tmp.addColumn(column); } statements.addAll(Arrays.asList(ct_change_tmp.generateStatements(database))); // copy rows to temporary table statements.add(new CopyRowsStatement(temp_table_name, tableName, copyColumns)); // delete original table statements.add(new DropTableStatement(catalogName, schemaName, temp_table_name, false)); // validate indices statements.add(new ReindexStatement(catalogName, schemaName, tableName)); // add remaining indices for (Index index_config : newIndices) { statements.add( new CreateIndexStatement( index_config.getName(), catalogName, schemaName, tableName, index_config.isUnique(), index_config.getAssociatedWithAsString(), index_config.getColumns().toArray(new String[index_config.getColumns().size()]))); } return statements; }
@Override public void checkDatabaseChangeLogTable( final boolean updateExistingNullChecksums, final DatabaseChangeLog databaseChangeLog, final Contexts contexts) throws DatabaseException { if (updateExistingNullChecksums && databaseChangeLog == null) { throw new DatabaseException("changeLog parameter is required if updating existing checksums"); } Executor executor = ExecutorService.getInstance().getExecutor(this); Table changeLogTable = SnapshotGeneratorFactory.getInstance() .getDatabaseChangeLogTable(new SnapshotControl(this, Table.class, Column.class), this); List<SqlStatement> statementsToExecute = new ArrayList<SqlStatement>(); boolean changeLogCreateAttempted = false; if (changeLogTable != null) { boolean hasDescription = changeLogTable.getColumn("DESCRIPTION") != null; boolean hasComments = changeLogTable.getColumn("COMMENTS") != null; boolean hasTag = changeLogTable.getColumn("TAG") != null; boolean hasLiquibase = changeLogTable.getColumn("LIQUIBASE") != null; boolean liquibaseColumnNotRightSize = false; if (!getConnection().getDatabaseProductName().equals("SQLite")) { liquibaseColumnNotRightSize = changeLogTable.getColumn("LIQUIBASE").getType().getColumnSize() != 20; } boolean hasOrderExecuted = changeLogTable.getColumn("ORDEREXECUTED") != null; boolean checksumNotRightSize = false; boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null; if (!hasDescription) { executor.comment("Adding missing databasechangelog.description column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "DESCRIPTION", "VARCHAR(255)", null)); } if (!hasTag) { executor.comment("Adding missing databasechangelog.tag column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "TAG", "VARCHAR(255)", null)); } if (!hasComments) { executor.comment("Adding missing databasechangelog.comments column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "COMMENTS", "VARCHAR(255)", null)); } if (!hasLiquibase) { executor.comment("Adding missing databasechangelog.liquibase column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", "VARCHAR(255)", null)); } if (!hasOrderExecuted) { executor.comment("Adding missing databasechangelog.orderexecuted column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "INT", null)); statementsToExecute.add( new UpdateStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) .addNewColumnValue("ORDEREXECUTED", -1)); statementsToExecute.add( new SetNullableStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "INT", false)); } if (checksumNotRightSize) { executor.comment("Modifying size of databasechangelog.md5sum column"); statementsToExecute.add( new ModifyDataTypeStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "MD5SUM", "VARCHAR(35)")); } if (liquibaseColumnNotRightSize) { executor.comment("Modifying size of databasechangelog.liquibase column"); statementsToExecute.add( new ModifyDataTypeStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", "VARCHAR(20)")); } if (!hasExecTypeColumn) { executor.comment("Adding missing databasechangelog.exectype column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "EXECTYPE", "VARCHAR(10)", null)); statementsToExecute.add( new UpdateStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) .addNewColumnValue("EXECTYPE", "EXECUTED")); statementsToExecute.add( new SetNullableStatement( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "EXECTYPE", "VARCHAR(10)", false)); } List<Map> md5sumRS = ExecutorService.getInstance() .getExecutor(this) .queryForList( new SelectFromDatabaseChangeLogStatement( new SelectFromDatabaseChangeLogStatement.ByNotNullCheckSum(), "MD5SUM")); if (md5sumRS.size() > 0) { String md5sum = md5sumRS.get(0).get("MD5SUM").toString(); if (!md5sum.startsWith(CheckSum.getCurrentVersion() + ":")) { executor.comment( "DatabaseChangeLog checksums are an incompatible version. Setting them to null so they will be updated on next database update"); statementsToExecute.add( new RawSqlStatement( "UPDATE " + escapeTableName( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) + " SET MD5SUM=null")); } } } else if (!changeLogCreateAttempted) { executor.comment("Create Database Change Log Table"); SqlStatement createTableStatement = new CreateDatabaseChangeLogTableStatement(); if (!canCreateChangeLogTable()) { throw new DatabaseException( "Cannot create " + escapeTableName( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) + " table for your database.\n\n" + "Please construct it manually using the following SQL as a base and re-run Liquibase:\n\n" + createTableStatement); } // If there is no table in the database for recording change history create one. statementsToExecute.add(createTableStatement); LogFactory.getLogger() .info( "Creating database history table with name: " + escapeTableName( getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName())); // } } for (SqlStatement sql : statementsToExecute) { executor.execute(sql); this.commit(); } if (updateExistingNullChecksums) { for (RanChangeSet ranChangeSet : this.getRanChangeSetList()) { if (ranChangeSet.getLastCheckSum() == null) { ChangeSet changeSet = databaseChangeLog.getChangeSet(ranChangeSet); if (changeSet != null && new ContextChangeSetFilter(contexts).accepts(changeSet) && new DbmsChangeSetFilter(this).accepts(changeSet)) { LogFactory.getLogger() .info( "Updating null or out of date checksum on changeSet " + changeSet + " to correct value"); executor.execute(new UpdateChangeSetChecksumStatement(changeSet)); } } } commit(); resetRanChangeSetList(); } }