public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException { try { boolean checkPassed; if (getForeignKeyTableName() == null) { checkPassed = DatabaseSnapshotGeneratorFactory.getInstance() .createSnapshot(database, getSchemaName(), null) .getForeignKey(getForeignKeyName()) != null; } else { // much faster if we can limit to correct table checkPassed = DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(database) .getForeignKeyByForeignKeyTable( getSchemaName(), getForeignKeyTableName(), getForeignKeyName(), database) != null; } if (!checkPassed) { String message = "Foreign Key " + database.escapeStringForDatabase(getForeignKeyName()); if (getForeignKeyTableName() != null) { message += " on table " + getForeignKeyTableName(); } message += " does not exist"; throw new PreconditionFailedException(message, changeLog, this); } } catch (DatabaseException e) { throw new PreconditionErrorException(e, changeLog, this); } }
@Override public boolean hasDatabaseChangeLogLockTable() throws DatabaseException { if (canCacheLiquibaseTableInfo && hasDatabaseChangeLogLockTable) { return true; } boolean hasTable = DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(this) .hasDatabaseChangeLogLockTable(this); if (canCacheLiquibaseTableInfo) { hasDatabaseChangeLogLockTable = hasTable; } return hasTable; }
@Override public void execute() throws BuildException { super.execute(); Liquibase liquibase = null; try { PrintStream writer = createPrintStream(); if (writer == null) { throw new BuildException("generateChangeLog requires outputFile to be set"); } liquibase = createLiquibase(); Database database = liquibase.getDatabase(); DiffControl diffControl = new DiffControl( getDefaultCatalogName(), getDefaultSchemaName(), null, null, getDiffTypes()); diffControl.setDataDir(getDataDir()); DatabaseSnapshot referenceSnapshot = DatabaseSnapshotGeneratorFactory.getInstance() .createSnapshot(database, diffControl, DiffControl.DatabaseRole.REFERENCE); DiffResult diffResult = DiffGeneratorFactory.getInstance() .compare(referenceSnapshot, new DatabaseSnapshot(database), diffControl); // diff.addStatusListener(new OutDiffStatusListener()); if (getChangeLogFile() == null) { new DiffToChangeLog(diffResult).print(writer); } else { new DiffToChangeLog(diffResult).print(getChangeLogFile()); } writer.flush(); writer.close(); } catch (Exception e) { throw new BuildException(e); } finally { closeDatabase(liquibase); } }
public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException { String currentSchemaName; try { currentSchemaName = getSchemaName() == null ? (database == null ? null : database.getDefaultSchemaName()) : getSchemaName(); if (!DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(database) .hasView(currentSchemaName, getViewName(), database)) { throw new PreconditionFailedException( "View " + database.escapeTableName(currentSchemaName, getViewName()) + " does not exist", changeLog, this); } } catch (PreconditionFailedException e) { throw e; } catch (Exception e) { throw new PreconditionErrorException(e, changeLog, this); } }
/** * Drops all objects owned by the connected user. * * @param schema */ @Override public void dropDatabaseObjects(String schema) throws DatabaseException { try { DatabaseSnapshotGeneratorFactory factory = DatabaseSnapshotGeneratorFactory.getInstance(); SnapshotContext context = new SnapshotContext(); context.setDatabase(this); context.setSchema(schema); context.setListeners(new HashSet<DiffStatusListener>()); DatabaseSnapshot snapshot = factory.createSnapshot(context); List<Change> dropChanges = new ArrayList<Change>(); for (View view : snapshot.getViews()) { DropViewChange dropChange = new DropViewChange(); dropChange.setViewName(view.getName()); dropChange.setSchemaName(schema); dropChanges.add(dropChange); } if (!supportsForeignKeyDisable()) { for (ForeignKey fk : snapshot.getForeignKeys()) { DropForeignKeyConstraintChange dropFK = new DropForeignKeyConstraintChange(); dropFK.setBaseTableSchemaName(schema); dropFK.setBaseTableName(fk.getForeignKeyTable().getName()); dropFK.setConstraintName(fk.getName()); dropChanges.add(dropFK); } } // for (Index index : snapshotGenerator.getIndexes()) { // DropIndexChange dropChange = new DropIndexChange(); // dropChange.setIndexName(index.getName()); // dropChange.setSchemaName(schema); // dropChange.setTableName(index.getTableName()); // // dropChanges.add(dropChange); // } for (Table table : snapshot.getTables()) { DropTableChange dropChange = new DropTableChange(); dropChange.setSchemaName(schema); dropChange.setTableName(table.getName()); if (supportsDropTableCascadeConstraints()) { dropChange.setCascadeConstraints(true); } dropChanges.add(dropChange); } if (this.supportsSequences()) { for (Sequence seq : snapshot.getSequences()) { DropSequenceChange dropChange = new DropSequenceChange(); dropChange.setSequenceName(seq.getName()); dropChange.setSchemaName(schema); dropChanges.add(dropChange); } } if (snapshot.hasDatabaseChangeLogTable()) { dropChanges.add(new AnonymousChange(new ClearDatabaseChangeLogTableStatement(schema))); } final boolean reEnableFK = supportsForeignKeyDisable() && disableForeignKeyChecks(); try { for (Change change : dropChanges) { for (SqlStatement statement : change.generateStatements(this)) { ExecutorService.getInstance().getExecutor(this).execute(statement); } } } finally { if (reEnableFK) { enableForeignKeyChecks(); } } } finally { this.commit(); } }
/** * This method will check the database ChangeLog table used to keep track of the changes in the * file. If the table does not exist it will create one otherwise it will not do anything besides * outputting a log message. * * @param updateExistingNullChecksums * @param contexts */ @Override public void checkDatabaseChangeLogTable( boolean updateExistingNullChecksums, DatabaseChangeLog databaseChangeLog, String... contexts) throws DatabaseException { Executor executor = ExecutorService.getInstance().getExecutor(this); Table changeLogTable = DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(this) .getDatabaseChangeLogTable(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 = changeLogTable.getColumn("LIQUIBASE").getColumnSize() != 20; boolean hasOrderExecuted = changeLogTable.getColumn("ORDEREXECUTED") != null; boolean checksumNotRightSize = changeLogTable.getColumn("MD5SUM").getColumnSize() != 35; boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null; if (!hasDescription) { executor.comment("Adding missing databasechangelog.description column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "DESCRIPTION", "VARCHAR(255)", null)); } if (!hasTag) { executor.comment("Adding missing databasechangelog.tag column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "TAG", "VARCHAR(255)", null)); } if (!hasComments) { executor.comment("Adding missing databasechangelog.comments column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "COMMENTS", "VARCHAR(255)", null)); } if (!hasLiquibase) { executor.comment("Adding missing databasechangelog.liquibase column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", "VARCHAR(255)", null)); } if (!hasOrderExecuted) { executor.comment("Adding missing databasechangelog.orderexecuted column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "INT", null)); statementsToExecute.add( new UpdateStatement(getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) .addNewColumnValue("ORDEREXECUTED", -1)); statementsToExecute.add( new SetNullableStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "INT", false)); } if (checksumNotRightSize) { executor.comment("Modifying size of databasechangelog.md5sum column"); statementsToExecute.add( new ModifyDataTypeStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "MD5SUM", "VARCHAR(35)")); } if (liquibaseColumnNotRightSize) { executor.comment("Modifying size of databasechangelog.liquibase column"); statementsToExecute.add( new ModifyDataTypeStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", "VARCHAR(20)")); } if (!hasExecTypeColumn) { executor.comment("Adding missing databasechangelog.exectype column"); statementsToExecute.add( new AddColumnStatement( getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "EXECTYPE", "VARCHAR(10)", null)); statementsToExecute.add( new UpdateStatement(getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) .addNewColumnValue("EXECTYPE", "EXECUTED")); statementsToExecute.add( new SetNullableStatement( 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(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(getDefaultSchemaName(), 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(getDefaultSchemaName(), 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(); this.ranChangeSetList = null; } }
public Table getTable(String schemaName, String tableName) throws DatabaseException { return DatabaseSnapshotGeneratorFactory.getInstance() .getGenerator(this) .getTable(schemaName, tableName, this); }