org.dbmaintain.structure.clear.impl.DefaultDBClearer Maven / Gradle / Ivy
/*
* Copyright DbMaintain.org
*
* Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
*
* 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 org.dbmaintain.structure.clear.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dbmaintain.database.Database;
import org.dbmaintain.database.Databases;
import org.dbmaintain.script.executedscriptinfo.ExecutedScriptInfoSource;
import org.dbmaintain.structure.clear.DBClearer;
import org.dbmaintain.structure.constraint.ConstraintsDisabler;
import org.dbmaintain.structure.model.DbItemIdentifier;
import org.dbmaintain.structure.model.DbItemType;
import org.dbmaintain.util.DbMaintainException;
import java.util.*;
import static org.dbmaintain.structure.model.DbItemIdentifier.getItemIdentifier;
import static org.dbmaintain.structure.model.DbItemIdentifier.getSchemaIdentifier;
import static org.dbmaintain.structure.model.DbItemType.*;
/**
* Implementation of {@link org.dbmaintain.structure.clear.DBClearer}. This implementation individually drops every table, view, materialized view, synonym,
* trigger and sequence in the database. A list of tables, views, ... that should be preserved can be specified at construction.
*
* NOTE: FK constraints give problems in MySQL and Derby
* The cascade in 'drop table A cascade;' does not work in MySQL-5.0
* The foreign key constraints will be disabled before this method is called.
*
* @author Tim Ducheyne
* @author Filip Neven
*/
public class DefaultDBClearer implements DBClearer {
/* The logger instance for this class */
private static Log logger = LogFactory.getLog(DefaultDBClearer.class);
/* Disables of constraints before clearing the database */
protected ConstraintsDisabler constraintsDisabler;
/* Clears the executed scripts table */
protected ExecutedScriptInfoSource executedScriptInfoSource;
/* Schemas, tables, views, materialized views, sequences, triggers and types that should not be dropped. */
protected Set itemsToPreserve = new HashSet();
protected Databases databases;
private MultiPassErrorHandler multiPassErrorHandler;
/**
* @param databases The db support instances, not null
* @param itemsToPreserve The schema's, tables, triggers etc that should not be dropped, not null
* @param constraintsDisabler Disables of constraints before clearing the database, not null
* @param executedScriptInfoSource Clears the executed scripts table, not null
*/
public DefaultDBClearer(Databases databases, Set itemsToPreserve, ConstraintsDisabler constraintsDisabler, ExecutedScriptInfoSource executedScriptInfoSource) {
this.databases = databases;
this.itemsToPreserve = itemsToPreserve;
this.constraintsDisabler = constraintsDisabler;
this.executedScriptInfoSource = executedScriptInfoSource;
assertItemsToPreserveExist(itemsToPreserve);
}
/**
* Clears the database schemas. This means, all the tables, views, constraints, triggers and sequences are dropped,
* so that the database schema is empty. The database items that are configured as items to preserve, are left
* untouched.
*/
public void clearDatabase() {
// Constraints are removed before clearing the database, to be sure there will be no conflicts when dropping tables
constraintsDisabler.disableConstraints();
for (Database database : databases.getDatabases()) {
if (database == null) {
continue;
}
clearDatabase(database);
}
executedScriptInfoSource.clearAllExecutedScripts();
}
protected void clearDatabase(Database database) {
for (String schemaName : database.getSchemaNames()) {
multiPassErrorHandler = new MultiPassErrorHandler();
// check whether schema needs to be preserved
if (itemsToPreserve.contains(getSchemaIdentifier(schemaName, database))) {
continue;
}
logger.info("Clearing database schema " + schemaName);
do {
dropSynonyms(database, schemaName);
dropViews(database, schemaName);
dropMaterializedViews(database, schemaName);
dropSequences(database, schemaName);
dropTables(database, schemaName);
dropTriggers(database, schemaName);
dropTypes(database, schemaName);
}
while (multiPassErrorHandler.continueExecutionAfterPass());
// todo drop functions, stored procedures.
}
}
/**
* Drops all tables.
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop tables from, not null
*/
protected void dropTables(Database database, String schemaName) {
Set tableNames = database.getTableNames(schemaName);
for (String tableName : tableNames) {
// check whether table needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(TABLE, schemaName, tableName, database))) {
continue;
}
logger.debug("Dropping table " + tableName + " in database schema " + schemaName);
try {
database.dropTable(schemaName, tableName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all views.
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop views from, not null
*/
protected void dropViews(Database database, String schemaName) {
Set viewNames = database.getViewNames(schemaName);
for (String viewName : viewNames) {
// check whether view needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(VIEW, schemaName, viewName, database))) {
continue;
}
logger.debug("Dropping view " + viewName + " in database schema " + schemaName);
try {
database.dropView(schemaName, viewName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all materialized views.
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop materialized views from, not null
*/
protected void dropMaterializedViews(Database database, String schemaName) {
if (!database.supportsMaterializedViews()) {
return;
}
Set materializedViewNames = database.getMaterializedViewNames(schemaName);
for (String materializedViewName : materializedViewNames) {
// check whether view needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(MATERIALIZED_VIEW, schemaName, materializedViewName, database))) {
continue;
}
logger.debug("Dropping materialized view " + materializedViewName + " in database schema " + schemaName);
try {
database.dropMaterializedView(schemaName, materializedViewName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all synonyms
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop synonyms from, not null
*/
protected void dropSynonyms(Database database, String schemaName) {
if (!database.supportsSynonyms()) {
return;
}
Set synonymNames = database.getSynonymNames(schemaName);
for (String synonymName : synonymNames) {
// check whether table needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(SYNONYM, schemaName, synonymName, database))) {
continue;
}
logger.debug("Dropping synonym " + synonymName + " in database schema " + schemaName);
try {
database.dropSynonym(schemaName, synonymName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all sequences
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop sequences from, not null
*/
protected void dropSequences(Database database, String schemaName) {
if (!database.supportsSequences()) {
return;
}
Set sequenceNames = database.getSequenceNames(schemaName);
for (String sequenceName : sequenceNames) {
// check whether sequence needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(SEQUENCE, schemaName, sequenceName, database))) {
continue;
}
logger.debug("Dropping sequence " + sequenceName + " in database schema " + schemaName);
try {
database.dropSequence(schemaName, sequenceName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all triggers
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop triggers from, not null
*/
protected void dropTriggers(Database database, String schemaName) {
if (!database.supportsTriggers()) {
return;
}
Set triggerNames = database.getTriggerNames(schemaName);
for (String triggerName : triggerNames) {
// check whether trigger needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(TRIGGER, schemaName, triggerName, database))) {
continue;
}
logger.debug("Dropping trigger " + triggerName + " in database schema " + schemaName);
try {
database.dropTrigger(schemaName, triggerName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
/**
* Drops all types.
*
* @param database The database support, not null
* @param schemaName The name of the schema to drop types from, not null
*/
protected void dropTypes(Database database, String schemaName) {
if (!database.supportsTypes()) {
return;
}
Set typeNames = database.getTypeNames(schemaName);
for (String typeName : typeNames) {
// check whether type needs to be preserved
if (itemsToPreserve.contains(getItemIdentifier(TYPE, schemaName, typeName, database))) {
continue;
}
logger.debug("Dropping type " + typeName + " in database schema " + schemaName);
try {
database.dropType(schemaName, typeName);
} catch (RuntimeException e) {
multiPassErrorHandler.addError(e);
}
}
}
protected void assertItemsToPreserveExist(Set itemsToPreserve) {
Map> schemaTables = new HashMap>();
Map> schemaViews = new HashMap>();
Map> schemaMaterializedViews = new HashMap>();
Map> schemaSequences = new HashMap>();
Map> schemaSynonyms = new HashMap>();
Map> schemaTriggers = new HashMap>();
Map> schemaTypes = new HashMap>();
for (DbItemIdentifier itemToPreserve : itemsToPreserve) {
Database database = databases.getDatabase(itemToPreserve.getDatabaseName());
switch (itemToPreserve.getType()) {
case SCHEMA:
if (!database.getSchemaNames().contains(itemToPreserve.getSchemaName())) {
throw new DbMaintainException("Schema to preserve does not exist: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which schema's need to be preserved. To assure nothing is dropped by mistake, no schema's will be dropped.");
}
break;
case TABLE:
Set tableNames = schemaTables.get(itemToPreserve.getSchema());
if (tableNames == null) {
tableNames = toDbItemIdentifiers(TABLE, database, itemToPreserve.getSchemaName(), database.getTableNames(itemToPreserve.getSchemaName()));
schemaTables.put(itemToPreserve.getSchema(), tableNames);
}
if (!itemToPreserve.isDbMaintainIdentifier() && !tableNames.contains(itemToPreserve)) {
throw new DbMaintainException("Table to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which tables need to be preserved. To assure nothing is dropped by mistake, no tables will be dropped.");
}
break;
case VIEW:
Set viewNames = schemaViews.get(itemToPreserve.getSchema());
if (viewNames == null) {
viewNames = toDbItemIdentifiers(VIEW, database, itemToPreserve.getSchemaName(), database.getViewNames(itemToPreserve.getSchemaName()));
schemaViews.put(itemToPreserve.getSchema(), viewNames);
}
if (!viewNames.contains(itemToPreserve)) {
throw new DbMaintainException("View to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which views need to be preserved. To assure nothing is dropped by mistake, no views will be dropped.");
}
break;
case MATERIALIZED_VIEW:
Set materializedViewNames = schemaMaterializedViews.get(itemToPreserve.getSchema());
if (materializedViewNames == null) {
if (database.supportsMaterializedViews()) {
materializedViewNames = toDbItemIdentifiers(MATERIALIZED_VIEW, database, itemToPreserve.getSchemaName(), database.getMaterializedViewNames(itemToPreserve.getSchemaName()));
} else {
materializedViewNames = Collections.emptySet();
}
schemaMaterializedViews.put(itemToPreserve.getSchema(), materializedViewNames);
}
if (!materializedViewNames.contains(itemToPreserve)) {
throw new DbMaintainException("Materialized view to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which materialized views need to be preserved. To assure nothing is dropped by mistake, no materialized views will be dropped.");
}
break;
case SEQUENCE:
Set sequenceNames = schemaSequences.get(itemToPreserve.getSchema());
if (sequenceNames == null) {
if (database.supportsSequences()) {
sequenceNames = toDbItemIdentifiers(SEQUENCE, database, itemToPreserve.getSchemaName(), database.getSequenceNames(itemToPreserve.getSchemaName()));
} else {
sequenceNames = Collections.emptySet();
}
schemaSequences.put(itemToPreserve.getSchema(), sequenceNames);
}
if (!sequenceNames.contains(itemToPreserve)) {
throw new DbMaintainException("Sequence to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which sequences need to be preserved. To assure nothing is dropped by mistake, no sequences will be dropped.");
}
break;
case SYNONYM:
Set synonymNames = schemaSynonyms.get(itemToPreserve.getSchema());
if (synonymNames == null) {
if (database.supportsSynonyms()) {
synonymNames = toDbItemIdentifiers(SYNONYM, database, itemToPreserve.getSchemaName(), database.getSynonymNames(itemToPreserve.getSchemaName()));
} else {
synonymNames = Collections.emptySet();
}
schemaSynonyms.put(itemToPreserve.getSchema(), synonymNames);
}
if (!synonymNames.contains(itemToPreserve)) {
throw new DbMaintainException("Synonym to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which synonyms need to be preserved. To assure nothing is dropped by mistake, no synonyms will be dropped.");
}
break;
case TRIGGER:
Set triggerNames = schemaTriggers.get(itemToPreserve.getSchema());
if (triggerNames == null) {
if (database.supportsTriggers()) {
triggerNames = toDbItemIdentifiers(TRIGGER, database, itemToPreserve.getSchemaName(), database.getTriggerNames(itemToPreserve.getSchemaName()));
} else {
triggerNames = Collections.emptySet();
}
schemaTriggers.put(itemToPreserve.getSchema(), triggerNames);
}
if (!triggerNames.contains(itemToPreserve)) {
throw new DbMaintainException("Trigger to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which triggers need to be preserved. To assure nothing is dropped by mistake, no triggers will be dropped.");
}
break;
case TYPE:
Set typeNames = schemaTypes.get(itemToPreserve.getSchema());
if (typeNames == null) {
if (database.supportsTypes()) {
typeNames = toDbItemIdentifiers(TYPE, database, itemToPreserve.getSchemaName(), database.getTypeNames(itemToPreserve.getSchemaName()));
} else {
typeNames = Collections.emptySet();
}
schemaTypes.put(itemToPreserve.getSchema(), typeNames);
}
if (!typeNames.contains(itemToPreserve)) {
throw new DbMaintainException("Type to preserve does not exist: " + itemToPreserve.getItemName() + " in schema: " + itemToPreserve.getSchemaName() +
".\nDbMaintain cannot determine which types need to be preserved. To assure nothing is dropped by mistake, no types will be dropped.");
}
break;
}
}
}
protected Set toDbItemIdentifiers(DbItemType type, Database database, String schemaName, Set itemNames) {
Set result = new HashSet();
for (String itemName : itemNames) {
result.add(getItemIdentifier(type, schemaName, itemName, database));
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy