use of org.jumpmind.db.model.Database in project symmetric-ds by JumpMind.
the class AbstractDdlBuilder method processTableStructureChanges.
/**
* Processes the changes to the structure of tables.
*
* @param currentModel
* The current database schema
* @param desiredModel
* The desired database schema
* @param changes
* The change objects
*/
protected void processTableStructureChanges(Database currentModel, Database desiredModel, Collection<TableChange> changes, StringBuilder ddl) {
filterChanges(changes);
LinkedHashMap<String, List<TableChange>> changesPerTable = new LinkedHashMap<String, List<TableChange>>();
LinkedHashMap<String, List<ForeignKey>> unchangedFKs = new LinkedHashMap<String, List<ForeignKey>>();
boolean caseSensitive = delimitedIdentifierModeOn;
// we use the names rather than the table objects
for (Iterator<TableChange> changeIt = changes.iterator(); changeIt.hasNext(); ) {
TableChange change = changeIt.next();
String name = change.getChangedTable().getName();
if (!caseSensitive) {
name = name.toUpperCase();
}
List<TableChange> changesForTable = (List<TableChange>) changesPerTable.get(name);
if (changesForTable == null) {
changesForTable = new ArrayList<TableChange>();
changesPerTable.put(name, changesForTable);
unchangedFKs.put(name, getUnchangedForeignKeys(currentModel, desiredModel, name));
}
changesForTable.add(change);
}
// we also need to drop the foreign keys of the unchanged tables
// referencing the changed tables
addRelevantFKsFromUnchangedTables(currentModel, desiredModel, changesPerTable.keySet(), unchangedFKs);
// we're dropping the unchanged foreign keys
for (Iterator<Map.Entry<String, List<ForeignKey>>> tableFKIt = unchangedFKs.entrySet().iterator(); tableFKIt.hasNext(); ) {
Map.Entry<String, List<ForeignKey>> entry = tableFKIt.next();
Table targetTable = findTable(desiredModel, (String) entry.getKey());
for (Iterator<ForeignKey> fkIt = entry.getValue().iterator(); fkIt.hasNext(); ) {
writeExternalForeignKeyDropStmt(targetTable, fkIt.next(), ddl);
}
}
// We're using a copy of the current model so that the table structure
// changes can modify it
Database copyOfCurrentModel = copy(currentModel);
for (Iterator<Map.Entry<String, List<TableChange>>> tableChangeIt = changesPerTable.entrySet().iterator(); tableChangeIt.hasNext(); ) {
Map.Entry<String, List<TableChange>> entry = tableChangeIt.next();
processTableStructureChanges(copyOfCurrentModel, desiredModel, entry.getKey(), entry.getValue(), ddl);
}
// and finally we're re-creating the unchanged foreign keys
for (Iterator<Map.Entry<String, List<ForeignKey>>> tableFKIt = unchangedFKs.entrySet().iterator(); tableFKIt.hasNext(); ) {
Map.Entry<String, List<ForeignKey>> entry = tableFKIt.next();
Table targetTable = findTable(desiredModel, (String) entry.getKey());
for (Iterator<ForeignKey> fkIt = entry.getValue().iterator(); fkIt.hasNext(); ) {
writeExternalForeignKeyCreateStmt(desiredModel, targetTable, fkIt.next(), ddl);
}
}
}
use of org.jumpmind.db.model.Database in project symmetric-ds by JumpMind.
the class AbstractDdlBuilder method processTableStructureChanges.
/**
* Processes the changes to the structure of a single table.
* Database-specific implementations might redefine this method, but it is
* usually sufficient to redefine the
* {@link #processTableStructureChanges(Database, Database, Table, Table, Map, List)}
* method instead.
*/
protected void processTableStructureChanges(Database currentModel, Database desiredModel, String tableName, List<TableChange> changes, StringBuilder ddl) {
StringBuilder tableDdl = new StringBuilder();
Database originalModel = copy(currentModel);
Table sourceTable = findTable(originalModel, tableName);
Table targetTable = findTable(desiredModel, tableName);
// we're enforcing a full rebuild in case of the addition of a required
// column without a default value that is not autoincrement
boolean requiresFullRebuild = false;
for (Iterator<TableChange> changeIt = changes.iterator(); !requiresFullRebuild && changeIt.hasNext(); ) {
TableChange change = changeIt.next();
if (change instanceof AddColumnChange) {
AddColumnChange addColumnChange = (AddColumnChange) change;
if (addColumnChange.getNewColumn().isRequired() && (addColumnChange.getNewColumn().getDefaultValue() == null) && !addColumnChange.getNewColumn().isAutoIncrement()) {
requiresFullRebuild = true;
}
}
}
if (!requiresFullRebuild) {
processTableStructureChanges(currentModel, desiredModel, sourceTable, targetTable, changes, tableDdl);
}
if (!changes.isEmpty()) {
// we can only copy the data if no required columns without default
// value and non-autoincrement have been added
boolean canMigrateData = true;
Table tempTable = getTemporaryTableFor(sourceTable);
for (Iterator<TableChange> it = changes.iterator(); canMigrateData && it.hasNext(); ) {
TableChange change = it.next();
if (change instanceof AddColumnChange) {
AddColumnChange addColumnChange = (AddColumnChange) change;
if (addColumnChange.getNewColumn().isRequired() && !addColumnChange.getNewColumn().isAutoIncrement() && (addColumnChange.getNewColumn().getDefaultValue() == null)) {
log.warn("Data cannot be retained in table " + change.getChangedTable().getName() + " because of the addition of the required column " + addColumnChange.getNewColumn().getName() + " . The data is backed up in " + tempTable + ", consider manually migrating the data back or dropping this temp table.");
canMigrateData = false;
}
}
}
Table realTargetTable = getRealTargetTableFor(desiredModel, sourceTable, targetTable);
dropTemporaryTable(tempTable, ddl);
createTemporaryTable(tempTable, ddl);
writeCopyDataStatement(sourceTable, tempTable, ddl);
/*
* Note that we don't drop the indices here because the DROP
* TABLE will take care of that Likewise, foreign keys have
* already been dropped as necessary
*/
dropTable(sourceTable, ddl, false, true);
createTable(realTargetTable, ddl, false, true);
if (canMigrateData) {
writeCopyDataStatement(tempTable, targetTable, ddl);
dropTemporaryTable(tempTable, ddl);
writeFixLastIdentityValues(targetTable, ddl);
}
} else {
ddl.append(tableDdl);
}
}
use of org.jumpmind.db.model.Database in project symmetric-ds by JumpMind.
the class AbstractDatabasePlatform method readDatabaseFromXml.
public Database readDatabaseFromXml(InputStream is, boolean alterCaseToMatchDatabaseDefaultCase) {
InputStreamReader reader = new InputStreamReader(is);
Database database = DatabaseXmlUtil.read(reader);
if (alterCaseToMatchDatabaseDefaultCase) {
alterCaseToMatchDatabaseDefaultCase(database);
}
return database;
}
use of org.jumpmind.db.model.Database in project symmetric-ds by JumpMind.
the class AbstractDatabasePlatform method readFromDatabase.
public Database readFromDatabase(Table... tables) {
Database fromDb = new Database();
for (Table tableFromXml : tables) {
Table tableFromDatabase = getTableFromCache(tableFromXml.getCatalog(), tableFromXml.getSchema(), tableFromXml.getName(), true);
if (tableFromDatabase != null) {
fromDb.addTable(tableFromDatabase);
}
}
fromDb.initialize();
return fromDb;
}
use of org.jumpmind.db.model.Database in project symmetric-ds by JumpMind.
the class MsSqlSymmetricDialect method readSymmetricSchemaFromXml.
@Override
public Database readSymmetricSchemaFromXml() {
Database db = super.readSymmetricSchemaFromXml();
if (parameterService.is(ParameterConstants.MSSQL_USE_NTYPES_FOR_SYNC)) {
Table table = db.findTable(TableConstants.getTableName(getTablePrefix(), TableConstants.SYM_DATA));
setColumnToNtext(table.getColumnWithName("row_data"));
setColumnToNtext(table.getColumnWithName("old_data"));
setColumnToNtext(table.getColumnWithName("pk_data"));
}
return db;
}
Aggregations