📄 sqlbuilder.java
字号:
CreationParameters params,
RemoveTableChange change) throws IOException
{
dropTable(change.getChangedTable());
change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
}
/**
* Processes the change representing the addition of a table.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param params The parameters used in the creation of new tables. Note that for existing
* tables, the parameters won't be applied
* @param change The change object
*/
protected void processChange(Database currentModel,
Database desiredModel,
CreationParameters params,
AddTableChange change) throws IOException
{
createTable(desiredModel, change.getNewTable(), params == null ? null : params.getParametersFor(change.getNewTable()));
change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
}
/**
* Processes the change representing the addition of a foreign key.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param params The parameters used in the creation of new tables. Note that for existing
* tables, the parameters won't be applied
* @param change The change object
*/
protected void processChange(Database currentModel,
Database desiredModel,
CreationParameters params,
AddForeignKeyChange change) throws IOException
{
writeExternalForeignKeyCreateStmt(desiredModel,
change.getChangedTable(),
change.getNewForeignKey());
change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
}
/**
* Processes the change representing the addition of an index.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param params The parameters used in the creation of new tables. Note that for existing
* tables, the parameters won't be applied
* @param change The change object
*/
protected void processChange(Database currentModel,
Database desiredModel,
CreationParameters params,
AddIndexChange change) throws IOException
{
writeExternalIndexCreateStmt(change.getChangedTable(), change.getNewIndex());
change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
}
/**
* Processes the changes to the structure of tables.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param params The parameters used in the creation of new tables. Note that for existing
* tables, the parameters won't be applied
* @param changes The change objects
*/
protected void processTableStructureChanges(Database currentModel,
Database desiredModel,
CreationParameters params,
Collection changes) throws IOException
{
ListOrderedMap changesPerTable = new ListOrderedMap();
ListOrderedMap unchangedFKs = new ListOrderedMap();
boolean caseSensitive = getPlatform().isDelimitedIdentifierModeOn();
// we first sort the changes for the tables
// however since the changes might contain source or target tables
// we use the names rather than the table objects
for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
{
TableChange change = (TableChange)changeIt.next();
String name = change.getChangedTable().getName();
if (!caseSensitive)
{
name = name.toUpperCase();
}
List changesForTable = (ArrayList)changesPerTable.get(name);
if (changesForTable == null)
{
changesForTable = new ArrayList();
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 tableFKIt = unchangedFKs.entrySet().iterator(); tableFKIt.hasNext();)
{
Map.Entry entry = (Map.Entry)tableFKIt.next();
Table targetTable = desiredModel.findTable((String)entry.getKey(), caseSensitive);
for (Iterator fkIt = ((List)entry.getValue()).iterator(); fkIt.hasNext();)
{
writeExternalForeignKeyDropStmt(targetTable, (ForeignKey)fkIt.next());
}
}
// We're using a copy of the current model so that the table structure changes can
// modify it
Database copyOfCurrentModel = null;
try
{
copyOfCurrentModel = (Database)currentModel.clone();
}
catch (CloneNotSupportedException ex)
{
throw new DdlUtilsException(ex);
}
for (Iterator tableChangeIt = changesPerTable.entrySet().iterator(); tableChangeIt.hasNext();)
{
Map.Entry entry = (Map.Entry)tableChangeIt.next();
Table targetTable = desiredModel.findTable((String)entry.getKey(), caseSensitive);
processTableStructureChanges(copyOfCurrentModel,
desiredModel,
(String)entry.getKey(),
params == null ? null : params.getParametersFor(targetTable),
(List)entry.getValue());
}
// and finally we're re-creating the unchanged foreign keys
for (Iterator tableFKIt = unchangedFKs.entrySet().iterator(); tableFKIt.hasNext();)
{
Map.Entry entry = (Map.Entry)tableFKIt.next();
Table targetTable = desiredModel.findTable((String)entry.getKey(), caseSensitive);
for (Iterator fkIt = ((List)entry.getValue()).iterator(); fkIt.hasNext();)
{
writeExternalForeignKeyCreateStmt(desiredModel, targetTable, (ForeignKey)fkIt.next());
}
}
}
/**
* Determines the unchanged foreign keys of the indicated table.
*
* @param currentModel The current model
* @param desiredModel The desired model
* @param tableName The name of the table
* @return The list of unchanged foreign keys
*/
private List getUnchangedForeignKeys(Database currentModel,
Database desiredModel,
String tableName)
{
ArrayList unchangedFKs = new ArrayList();
boolean caseSensitive = getPlatform().isDelimitedIdentifierModeOn();
Table sourceTable = currentModel.findTable(tableName, caseSensitive);
Table targetTable = desiredModel.findTable(tableName, caseSensitive);
for (int idx = 0; idx < targetTable.getForeignKeyCount(); idx++)
{
ForeignKey targetFK = targetTable.getForeignKey(idx);
ForeignKey sourceFK = sourceTable.findForeignKey(targetFK, caseSensitive);
if (sourceFK != null)
{
unchangedFKs.add(targetFK);
}
}
return unchangedFKs;
}
/**
* Adds the foreign keys of the unchanged tables that reference changed tables
* to the given map.
*
* @param currentModel The current model
* @param desiredModel The desired model
* @param namesOfKnownChangedTables The known names of changed tables
* @param fksPerTable The map table name -> foreign keys to which
* found foreign keys will be added to
*/
private void addRelevantFKsFromUnchangedTables(Database currentModel,
Database desiredModel,
Set namesOfKnownChangedTables,
Map fksPerTable)
{
boolean caseSensitive = getPlatform().isDelimitedIdentifierModeOn();
for (int tableIdx = 0; tableIdx < desiredModel.getTableCount(); tableIdx++)
{
Table targetTable = desiredModel.getTable(tableIdx);
String name = targetTable.getName();
Table sourceTable = currentModel.findTable(name, caseSensitive);
List relevantFks = null;
if (!caseSensitive)
{
name = name.toUpperCase();
}
if ((sourceTable != null) && !namesOfKnownChangedTables.contains(name))
{
for (int fkIdx = 0; fkIdx < targetTable.getForeignKeyCount(); fkIdx++)
{
ForeignKey targetFk = targetTable.getForeignKey(fkIdx);
ForeignKey sourceFk = sourceTable.findForeignKey(targetFk, caseSensitive);
String refName = targetFk.getForeignTableName();
if (!caseSensitive)
{
refName = refName.toUpperCase();
}
if ((sourceFk != null) && namesOfKnownChangedTables.contains(refName))
{
if (relevantFks == null)
{
relevantFks = new ArrayList();
fksPerTable.put(name, relevantFks);
}
relevantFks.add(targetFk);
}
}
}
}
}
/**
* 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.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param tableName The name of the changed table
* @param parameters The creation parameters for the desired table
* @param changes The change objects for this table
*/
protected void processTableStructureChanges(Database currentModel,
Database desiredModel,
String tableName,
Map parameters,
List changes) throws IOException
{
Table sourceTable = currentModel.findTable(tableName, getPlatform().isDelimitedIdentifierModeOn());
Table targetTable = desiredModel.findTable(tableName, getPlatform().isDelimitedIdentifierModeOn());
processTableStructureChanges(currentModel, desiredModel, sourceTable, targetTable, parameters, changes);
if (!changes.isEmpty())
{
Table tempTable = getTemporaryTableFor(desiredModel, targetTable);
Table realTargetTable = getRealTargetTableFor(desiredModel, sourceTable, targetTable);
createTemporaryTable(desiredModel, tempTable, parameters);
writeCopyDataStatement(sourceTable, tempTable);
// 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);
createTable(desiredModel, realTargetTable, parameters);
writeCopyDataStatement(tempTable, targetTable);
dropTemporaryTable(desiredModel, tempTable);
}
}
/**
* Allows database-specific implementations to handle changes in a database
* specific manner. Any handled change should be applied to the given current
* model (which is a copy of the real original model) and be removed from the
* list of changes.<br/>
* In the default implementation, all {@link AddPrimaryKeyChange} changes are
* applied via an <code>ALTER TABLE ADD CONSTRAINT</code> statement.
*
* @param currentModel The current database schema
* @param desiredModel The desired database schema
* @param sourceTable The original table
* @param targetTable The desired table
* @param parameters The creation parameters for the table
* @param changes The change objects for the target table
*/
protected void processTableStructureChanges(Database currentModel,
Database desiredModel,
Table sourceTable,
Table targetTable,
Map parameters,
List changes) throws IOException
{
if (changes.size() == 1)
{
TableChange change = (TableChange)changes.get(0);
if (change instanceof AddPrimaryKeyChange)
{
processChange(currentModel, desiredModel, (AddPrimaryKeyChange)change);
changes.clear();
}
}
}
/**
* Creates a temporary table object that corresponds to the given table.
* Database-specific implementations may redefine this method if e.g. the
* database directly supports temporary tables. The default implementation
* simply appends an underscore to the table name and uses that as the
* table name.
*
* @param targetModel The target database
* @param targetTable The target table
* @return The temporary table
*/
protected Table getTemporaryTableFor(Database targetModel, Table targetTable) throws IOException
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -