You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ddlutils-dev@db.apache.org by to...@apache.org on 2007/12/10 09:21:39 UTC
svn commit: r602807 [2/15] - in /db/ddlutils/trunk: ./
src/java/org/apache/ddlutils/ src/java/org/apache/ddlutils/alteration/
src/java/org/apache/ddlutils/model/ src/java/org/apache/ddlutils/platform/
src/java/org/apache/ddlutils/platform/axion/ src/ja...
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java Mon Dec 10 00:20:47 2007
@@ -23,15 +23,16 @@
import java.util.HashMap;
import java.util.List;
-import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.CloneHelper;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
import org.apache.ddlutils.model.Index;
import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.util.StringUtils;
/**
* Compares two database models and creates change objects that express how to
@@ -39,8 +40,6 @@
* are changed in the process, however, it is also assumed that the models do not
* change in between.
*
- * TODO: Add support and tests for the change of the column order
- *
* @version $Revision: $
*/
public class ModelComparator
@@ -50,19 +49,79 @@
/** The platform information. */
private PlatformInfo _platformInfo;
+ /** The predicate that defines which changes are supported by the platform. */
+ private TableDefinitionChangesPredicate _tableDefCangePredicate;
+ /** The object clone helper. */
+ private CloneHelper _cloneHelper = new CloneHelper();
/** Whether comparison is case sensitive. */
private boolean _caseSensitive;
+ /** Whether the comparator should generate {@link PrimaryKeyChange} objects. */
+ private boolean _generatePrimaryKeyChanges = true;
+ /** Whether {@link RemoveColumnChange} objects for primary key columns are enough or
+ additional primary key change objects are necessary. */
+ private boolean _canDropPrimaryKeyColumns = true;
/**
* Creates a new model comparator object.
*
- * @param platformInfo The platform info
- * @param caseSensitive Whether comparison is case sensitive
+ * @param platformInfo The platform info
+ * @param tableDefChangePredicate The predicate that defines whether tables changes are supported
+ * by the platform or not; all changes are supported if this is null
+ * @param caseSensitive Whether comparison is case sensitive
+ */
+ public ModelComparator(PlatformInfo platformInfo,
+ TableDefinitionChangesPredicate tableDefChangePredicate,
+ boolean caseSensitive)
+ {
+ _platformInfo = platformInfo;
+ _caseSensitive = caseSensitive;
+ _tableDefCangePredicate = tableDefChangePredicate;
+ }
+
+ /**
+ * Specifies whether the comparator should generate {@link PrimaryKeyChange} objects or a
+ * pair of {@link RemovePrimaryKeyChange} and {@link AddPrimaryKeyChange} objects instead.
+ * The default value is <code>true</code>.
+ *
+ * @param generatePrimaryKeyChanges Whether to create {@link PrimaryKeyChange} objects
+ */
+ public void setGeneratePrimaryKeyChanges(boolean generatePrimaryKeyChanges)
+ {
+ _generatePrimaryKeyChanges = generatePrimaryKeyChanges;
+ }
+
+ /**
+ * Specifies whether the {@link RemoveColumnChange} are fine even for primary key columns.
+ * If the platform cannot drop primary key columns, set this to <code>false</code> and the
+ * comparator will create additional primary key changes.
+ * The default value is <code>true</code>.
+ *
+ * @param canDropPrimaryKeyColumns Whether {@link RemoveColumnChange} objecs for primary
+ * key columns are ok
+ */
+ public void setCanDropPrimaryKeyColumns(boolean canDropPrimaryKeyColumns)
+ {
+ _canDropPrimaryKeyColumns = canDropPrimaryKeyColumns;
+ }
+
+ /**
+ * Returns the info object for the platform.
+ *
+ * @return The platform info object
*/
- public ModelComparator(PlatformInfo platformInfo, boolean caseSensitive)
+ protected PlatformInfo getPlatformInfo()
{
- _platformInfo = platformInfo;
- _caseSensitive = caseSensitive;
+ return _platformInfo;
+ }
+
+ /**
+ * Determines whether comparison should be case sensitive.
+ *
+ * @return <code>true</code> if case matters
+ */
+ protected boolean isCaseSensitive()
+ {
+ return _caseSensitive;
}
/**
@@ -75,217 +134,661 @@
*/
public List compare(Database sourceModel, Database targetModel)
{
+ Database intermediateModel = _cloneHelper.clone(sourceModel);
+
+ return compareModels(sourceModel, intermediateModel, targetModel);
+ }
+
+ /**
+ * Compares the given source and target models and creates change objects to get from
+ * the source to the target one. These changes will be applied to the given
+ * intermediate model (the other two won't be changed), so that it will be equal to
+ * the target model after this model has finished.
+ *
+ * @param sourceModel The source model
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param targetModel The target model
+ * @return The changes
+ */
+ protected List compareModels(Database sourceModel,
+ Database intermediateModel,
+ Database targetModel)
+ {
ArrayList changes = new ArrayList();
- for (int tableIdx = 0; tableIdx < targetModel.getTableCount(); tableIdx++)
+ changes.addAll(checkForRemovedForeignKeys(sourceModel, intermediateModel, targetModel));
+ changes.addAll(checkForRemovedTables(sourceModel, intermediateModel, targetModel));
+
+ for (int tableIdx = 0; tableIdx < intermediateModel.getTableCount(); tableIdx++)
{
- Table targetTable = targetModel.getTable(tableIdx);
- Table sourceTable = sourceModel.findTable(targetTable.getName(), _caseSensitive);
+ Table intermediateTable = intermediateModel.getTable(tableIdx);
+ Table sourceTable = sourceModel.findTable(intermediateTable.getName(), _caseSensitive);
+ Table targetTable = targetModel.findTable(intermediateTable.getName(), _caseSensitive);
+ List tableChanges = compareTables(sourceModel, sourceTable,
+ intermediateModel, intermediateTable,
+ targetModel, targetTable);
+
+ changes.addAll(tableChanges);
+ }
- if (sourceTable == null)
+ changes.addAll(checkForAddedTables(sourceModel, intermediateModel, targetModel));
+ changes.addAll(checkForAddedForeignKeys(sourceModel, intermediateModel, targetModel));
+ return changes;
+ }
+
+ /**
+ * Creates change objects for foreign keys that are present in the given source model but are no longer in the target
+ * model, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param targetModel The target model
+ * @return The changes
+ */
+ protected List checkForRemovedForeignKeys(Database sourceModel,
+ Database intermediateModel,
+ Database targetModel)
+ {
+ List changes = new ArrayList();
+
+ for (int tableIdx = 0; tableIdx < intermediateModel.getTableCount(); tableIdx++)
+ {
+ Table intermediateTable = intermediateModel.getTable(tableIdx);
+ Table targetTable = targetModel.findTable(intermediateTable.getName(), _caseSensitive);
+ ForeignKey[] intermediateFks = intermediateTable.getForeignKeys();
+
+ // Dropping foreign keys from tables to be removed might not be necessary, but some databases might require it
+ for (int fkIdx = 0; fkIdx < intermediateFks.length; fkIdx++)
{
- if (_log.isInfoEnabled())
- {
- _log.info("Table " + targetTable.getName() + " needs to be added");
- }
- changes.add(new AddTableChange(targetTable));
- for (int fkIdx = 0; fkIdx < targetTable.getForeignKeyCount(); fkIdx++)
+ ForeignKey sourceFk = intermediateFks[fkIdx];
+ ForeignKey targetFk = targetTable == null ? null : findCorrespondingForeignKey(targetTable, sourceFk);
+
+ if (targetFk == null)
{
- // we have to use target table's definition here because the
- // complete table is new
- changes.add(new AddForeignKeyChange(targetTable, targetTable.getForeignKey(fkIdx)));
+ if (_log.isInfoEnabled())
+ {
+ _log.info("Foreign key " + sourceFk + " needs to be removed from table " + intermediateTable.getName());
+ }
+
+ RemoveForeignKeyChange fkChange = new RemoveForeignKeyChange(intermediateTable.getName(), sourceFk);
+
+ changes.add(fkChange);
+ fkChange.apply(intermediateModel, _caseSensitive);
}
}
- else
+ }
+ return changes;
+ }
+
+ /**
+ * Creates change objects for foreign keys that are not present in the given source model but are in the target
+ * model, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param targetModel The target model
+ * @return The changes
+ */
+ protected List checkForAddedForeignKeys(Database sourceModel,
+ Database intermediateModel,
+ Database targetModel)
+ {
+ List changes = new ArrayList();
+
+ for (int tableIdx = 0; tableIdx < targetModel.getTableCount(); tableIdx++)
+ {
+ Table targetTable = targetModel.getTable(tableIdx);
+ Table intermediateTable = intermediateModel.findTable(targetTable.getName(), _caseSensitive);
+
+ for (int fkIdx = 0; fkIdx < targetTable.getForeignKeyCount(); fkIdx++)
{
- changes.addAll(compareTables(sourceModel, sourceTable, targetModel, targetTable));
+ ForeignKey targetFk = targetTable.getForeignKey(fkIdx);
+ ForeignKey intermediateFk = findCorrespondingForeignKey(intermediateTable, targetFk);
+
+ if (intermediateFk == null)
+ {
+ if (_log.isInfoEnabled())
+ {
+ _log.info("Foreign key " + targetFk + " needs to be added to table " + intermediateTable.getName());
+ }
+
+ intermediateFk = _cloneHelper.clone(targetFk, intermediateTable, intermediateModel, _caseSensitive);
+
+ AddForeignKeyChange fkChange = new AddForeignKeyChange(intermediateTable.getName(), intermediateFk);
+
+ changes.add(fkChange);
+ fkChange.apply(intermediateModel, _caseSensitive);
+ }
}
}
+ return changes;
+ }
+
+ /**
+ * Creates change objects for tables that are present in the given source model but are no longer in the target
+ * model, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param targetModel The target model
+ * @return The changes
+ */
+ protected List checkForRemovedTables(Database sourceModel,
+ Database intermediateModel,
+ Database targetModel)
+ {
+ List changes = new ArrayList();
+ Table[] intermediateTables = intermediateModel.getTables();
- for (int tableIdx = 0; tableIdx < sourceModel.getTableCount(); tableIdx++)
+ for (int tableIdx = 0; tableIdx < intermediateTables.length; tableIdx++)
{
- Table sourceTable = sourceModel.getTable(tableIdx);
- Table targetTable = targetModel.findTable(sourceTable.getName(), _caseSensitive);
+ Table intermediateTable = intermediateTables[tableIdx];
+ Table targetTable = targetModel.findTable(intermediateTable.getName(), _caseSensitive);
- if ((targetTable == null) && (sourceTable.getName() != null) && (sourceTable.getName().length() > 0))
+ if (targetTable == null)
{
if (_log.isInfoEnabled())
{
- _log.info("Table " + sourceTable.getName() + " needs to be removed");
- }
- changes.add(new RemoveTableChange(sourceTable));
- // we assume that the target model is sound, ie. that there are no longer any foreign
- // keys to this table in the target model; thus we already have removeFK changes for
- // these from the compareTables method and we only need to create changes for the fks
- // originating from this table
- for (int fkIdx = 0; fkIdx < sourceTable.getForeignKeyCount(); fkIdx++)
- {
- changes.add(new RemoveForeignKeyChange(sourceTable, sourceTable.getForeignKey(fkIdx)));
+ _log.info("Table " + intermediateTable.getName() + " needs to be removed");
}
+
+ RemoveTableChange tableChange = new RemoveTableChange(intermediateTable.getName());
+
+ changes.add(tableChange);
+ tableChange.apply(intermediateModel, _caseSensitive);
}
}
return changes;
}
/**
- * Compares the two tables and returns the changes necessary to create the second
- * table from the first one.
- *
- * @param sourceModel The source model which contains the source table
- * @param sourceTable The source table
- * @param targetModel The target model which contains the target table
- * @param targetTable The target table
+ * Creates change objects for tables that are not present in the given source model but are in the target
+ * model, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param targetModel The target model
* @return The changes
*/
- public List compareTables(Database sourceModel,
- Table sourceTable,
- Database targetModel,
- Table targetTable)
+ protected List checkForAddedTables(Database sourceModel,
+ Database intermediateModel,
+ Database targetModel)
{
- ArrayList changes = new ArrayList();
+ List changes = new ArrayList();
- for (int fkIdx = 0; fkIdx < sourceTable.getForeignKeyCount(); fkIdx++)
+ for (int tableIdx = 0; tableIdx < targetModel.getTableCount(); tableIdx++)
{
- ForeignKey sourceFk = sourceTable.getForeignKey(fkIdx);
- ForeignKey targetFk = findCorrespondingForeignKey(targetTable, sourceFk);
+ Table targetTable = targetModel.getTable(tableIdx);
+ Table intermediateTable = intermediateModel.findTable(targetTable.getName(), _caseSensitive);
- if (targetFk == null)
+ if (intermediateTable == null)
{
if (_log.isInfoEnabled())
{
- _log.info("Foreign key " + sourceFk + " needs to be removed from table " + sourceTable.getName());
+ _log.info("Table " + targetTable.getName() + " needs to be added");
}
- changes.add(new RemoveForeignKeyChange(sourceTable, sourceFk));
+
+ // we're using a clone of the target table, and remove all foreign
+ // keys as these will be added later
+ intermediateTable = _cloneHelper.clone(targetTable, true, false, intermediateModel, _caseSensitive);
+
+ AddTableChange tableChange = new AddTableChange(intermediateTable);
+
+ changes.add(tableChange);
+ tableChange.apply(intermediateModel, _caseSensitive);
}
}
+ return changes;
+ }
- for (int fkIdx = 0; fkIdx < targetTable.getForeignKeyCount(); fkIdx++)
- {
- ForeignKey targetFk = targetTable.getForeignKey(fkIdx);
- ForeignKey sourceFk = findCorrespondingForeignKey(sourceTable, targetFk);
+ /**
+ * Compares the two tables and returns the changes necessary to create the second
+ * table from the first one.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to which the changes will be applied incrementally
+ * @param intermediateTable The table corresponding to the source table in the intermediate model
+ * @param targetModel The target model which contains the target table
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List compareTables(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ ArrayList changes = new ArrayList();
+
+ changes.addAll(checkForRemovedIndexes(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+
+ ArrayList tableDefinitionChanges = new ArrayList();
+ Table tmpTable = _cloneHelper.clone(intermediateTable, true, false, intermediateModel, _caseSensitive);
- if (sourceFk == null)
+ tableDefinitionChanges.addAll(checkForRemovedColumns(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+ tableDefinitionChanges.addAll(checkForChangeOfColumnOrder(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+ tableDefinitionChanges.addAll(checkForChangedColumns(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+ tableDefinitionChanges.addAll(checkForAddedColumns(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+ tableDefinitionChanges.addAll(checkForPrimaryKeyChanges(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+
+ if (!tableDefinitionChanges.isEmpty())
+ {
+ if ((_tableDefCangePredicate == null) || _tableDefCangePredicate.areSupported(tmpTable, tableDefinitionChanges))
{
- if (_log.isInfoEnabled())
+ changes.addAll(tableDefinitionChanges);
+ }
+ else
+ {
+ // we need to recreate the table; for this to work we need to remove foreign keys to and from the table
+ // however, we don't have to add them back here as there is a check for added foreign keys/indexes
+ // later on anyways
+ // we also don't have to drop indexes on the original table
+
+ ForeignKey[] fks = intermediateTable.getForeignKeys();
+
+ for (int fkIdx = 0; fkIdx < fks.length; fkIdx++)
{
- _log.info("Foreign key " + targetFk + " needs to be created for table " + sourceTable.getName());
+ RemoveForeignKeyChange fkChange = new RemoveForeignKeyChange(intermediateTable.getName(), fks[fkIdx]);
+
+ changes.add(fkChange);
+ fkChange.apply(intermediateModel, _caseSensitive);
+ }
+ for (int tableIdx = 0; tableIdx < intermediateModel.getTableCount(); tableIdx++)
+ {
+ Table curTable = intermediateModel.getTable(tableIdx);
+
+ if (curTable != intermediateTable)
+ {
+ ForeignKey[] curFks = curTable.getForeignKeys();
+
+ for (int fkIdx = 0; fkIdx < curFks.length; fkIdx++)
+ {
+ if ((_caseSensitive && curFks[fkIdx].getForeignTableName().equals(intermediateTable.getName())) ||
+ (!_caseSensitive && curFks[fkIdx].getForeignTableName().equalsIgnoreCase(intermediateTable.getName())))
+ {
+ RemoveForeignKeyChange fkChange = new RemoveForeignKeyChange(curTable.getName(), curFks[fkIdx]);
+
+ changes.add(fkChange);
+ fkChange.apply(intermediateModel, _caseSensitive);
+ }
+ }
+ }
}
- // we have to use the target table here because the foreign key might
- // reference a new column
- changes.add(new AddForeignKeyChange(targetTable, targetFk));
+
+ RecreateTableChange tableChange = new RecreateTableChange(intermediateTable.getName(),
+ intermediateTable,
+ new ArrayList(tableDefinitionChanges));
+
+ changes.add(tableChange);
+ tableChange.apply(intermediateModel, _caseSensitive);
}
}
+
+ changes.addAll(checkForAddedIndexes(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+
+ return changes;
+ }
+
+ /**
+ * Returns the names of the columns in the intermediate table corresponding to the given column objects.
+ *
+ * @param columns The column objects
+ * @param intermediateTable The intermediate table
+ * @return The column names
+ */
+ protected String[] getIntermediateColumnNamesFor(Column[] columns, Table intermediateTable)
+ {
+ String[] result = new String[columns.length];
- for (int indexIdx = 0; indexIdx < sourceTable.getIndexCount(); indexIdx++)
+ for (int idx = 0; idx < columns.length; idx++)
{
- Index sourceIndex = sourceTable.getIndex(indexIdx);
+ result[idx] = intermediateTable.findColumn(columns[idx].getName(), _caseSensitive).getName();
+ }
+ return result;
+ }
+
+ /**
+ * Creates change objects for indexes that are present in the given source table but are no longer in the target
+ * table, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForRemovedIndexes(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
+ Index[] indexes = intermediateTable.getIndices();
+
+ for (int indexIdx = 0; indexIdx < indexes.length; indexIdx++)
+ {
+ Index sourceIndex = indexes[indexIdx];
Index targetIndex = findCorrespondingIndex(targetTable, sourceIndex);
if (targetIndex == null)
{
if (_log.isInfoEnabled())
{
- _log.info("Index " + sourceIndex.getName() + " needs to be removed from table " + sourceTable.getName());
+ _log.info("Index " + sourceIndex.getName() + " needs to be removed from table " + intermediateTable.getName());
}
- changes.add(new RemoveIndexChange(sourceTable, sourceIndex));
+
+ RemoveIndexChange change = new RemoveIndexChange(intermediateTable.getName(), sourceIndex);
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
}
+ return changes;
+ }
+
+ /**
+ * Creates change objects for indexes that are not present in the given source table but are in the target
+ * table, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForAddedIndexes(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
+
for (int indexIdx = 0; indexIdx < targetTable.getIndexCount(); indexIdx++)
{
Index targetIndex = targetTable.getIndex(indexIdx);
- Index sourceIndex = findCorrespondingIndex(sourceTable, targetIndex);
+ Index sourceIndex = findCorrespondingIndex(intermediateTable, targetIndex);
if (sourceIndex == null)
{
if (_log.isInfoEnabled())
{
- _log.info("Index " + targetIndex.getName() + " needs to be created for table " + sourceTable.getName());
+ _log.info("Index " + targetIndex.getName() + " needs to be created for table " + intermediateTable.getName());
}
- // we have to use the target table here because the index might
- // reference a new column
- changes.add(new AddIndexChange(targetTable, targetIndex));
+
+ Index clonedIndex = _cloneHelper.clone(targetIndex, intermediateTable, _caseSensitive);
+ AddIndexChange change = new AddIndexChange(intermediateTable.getName(), clonedIndex);
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
}
+ return changes;
+ }
- HashMap addColumnChanges = new HashMap();
+ /**
+ * Checks for changes in the column order between the given source and target table, creates change objects for these and
+ * applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForChangeOfColumnOrder(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
+ List targetOrder = new ArrayList();
+ int numChangedPKs = 0;
for (int columnIdx = 0; columnIdx < targetTable.getColumnCount(); columnIdx++)
{
Column targetColumn = targetTable.getColumn(columnIdx);
- Column sourceColumn = sourceTable.findColumn(targetColumn.getName(), _caseSensitive);
+ Column sourceColumn = intermediateTable.findColumn(targetColumn.getName(), _caseSensitive);
- if (sourceColumn == null)
+ if (sourceColumn != null)
{
- if (_log.isInfoEnabled())
+ targetOrder.add(sourceColumn);
+ }
+ }
+
+ HashMap newPositions = new HashMap();
+
+ for (int columnIdx = 0; columnIdx < intermediateTable.getColumnCount(); columnIdx++)
+ {
+ Column sourceColumn = intermediateTable.getColumn(columnIdx);
+ int targetIdx = targetOrder.indexOf(sourceColumn);
+
+ if ((targetIdx >= 0) && (targetIdx != columnIdx))
+ {
+ newPositions.put(sourceColumn.getName(), new Integer(targetIdx));
+ if (sourceColumn.isPrimaryKey())
{
- _log.info("Column " + targetColumn.getName() + " needs to be created for table " + sourceTable.getName());
+ numChangedPKs++;
}
+ }
+ }
- AddColumnChange change = new AddColumnChange(sourceTable,
- targetColumn,
- columnIdx > 0 ? targetTable.getColumn(columnIdx - 1) : null,
- columnIdx < targetTable.getColumnCount() - 1 ? targetTable.getColumn(columnIdx + 1) : null);
+ if (!newPositions.isEmpty())
+ {
+ ColumnOrderChange change = new ColumnOrderChange(intermediateTable.getName(), newPositions);
- changes.add(change);
- addColumnChanges.put(targetColumn, change);
+ change.apply(intermediateModel, _caseSensitive);
+ if (numChangedPKs > 1)
+ {
+ // create pk change that only covers the order change
+ // fortunately, the order change will have adjusted the pk order already
+ changes.add(new PrimaryKeyChange(intermediateTable.getName(),
+ getIntermediateColumnNamesFor(intermediateTable.getPrimaryKeyColumns(), intermediateTable)));
}
- else
+ changes.add(change);
+ }
+ return changes;
+ }
+
+ /**
+ * Creates change objects for columns that are present in the given source table but are no longer in the target
+ * table, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForRemovedColumns(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ // if the platform does not support dropping pk columns, then the pk handling above will
+ // generate appropriate pk changes
+
+ List changes = new ArrayList();
+ Column[] columns = intermediateTable.getColumns();
+
+ for (int columnIdx = 0; columnIdx < columns.length; columnIdx++)
+ {
+ Column sourceColumn = columns[columnIdx];
+ Column targetColumn = targetTable.findColumn(sourceColumn.getName(), _caseSensitive);
+
+ if (targetColumn == null)
{
- changes.addAll(compareColumns(sourceTable, sourceColumn, targetTable, targetColumn));
+ if (_log.isInfoEnabled())
+ {
+ _log.info("Column " + sourceColumn.getName() + " needs to be removed from table " + intermediateTable.getName());
+ }
+
+ RemoveColumnChange change = new RemoveColumnChange(intermediateTable.getName(), sourceColumn.getName());
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
}
- // if the last columns in the target table are added, then we note this at the changes
- for (int columnIdx = targetTable.getColumnCount() - 1; columnIdx >= 0; columnIdx--)
+ return changes;
+ }
+
+ /**
+ * Creates change objects for columns that are not present in the given source table but are in the target
+ * table, and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForAddedColumns(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
+
+ for (int columnIdx = 0; columnIdx < targetTable.getColumnCount(); columnIdx++)
{
- Column targetColumn = targetTable.getColumn(columnIdx);
- AddColumnChange change = (AddColumnChange)addColumnChanges.get(targetColumn);
+ Column targetColumn = targetTable.getColumn(columnIdx);
+ Column sourceColumn = intermediateTable.findColumn(targetColumn.getName(), _caseSensitive);
- if (change == null)
+ if (sourceColumn == null)
{
- // column was not added, so we can ignore any columns before it that were added
- break;
+ String prevColumn = (columnIdx > 0 ? intermediateTable.getColumn(columnIdx - 1).getName() : null);
+ String nextColumn = (columnIdx < intermediateTable.getColumnCount() ? intermediateTable.getColumn(columnIdx).getName() : null);
+ Column clonedColumn = _cloneHelper.clone(targetColumn, false);
+ AddColumnChange change = new AddColumnChange(intermediateTable.getName(), clonedColumn, prevColumn, nextColumn);
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
- else
+ }
+ return changes;
+ }
+
+ /**
+ * Creates change objects for columns that have a different in the given source and target table, and applies them
+ * to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForChangedColumns(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
+
+ for (int columnIdx = 0; columnIdx < targetTable.getColumnCount(); columnIdx++)
+ {
+ Column targetColumn = targetTable.getColumn(columnIdx);
+ Column sourceColumn = intermediateTable.findColumn(targetColumn.getName(), _caseSensitive);
+
+ if (sourceColumn != null)
{
- change.setAtEnd(true);
+ ColumnDefinitionChange change = compareColumns(intermediateTable, sourceColumn, targetTable, targetColumn);
+
+ if (change != null)
+ {
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
+ }
}
}
+ return changes;
+ }
+ /**
+ * Creates change objects for primary key differences (primary key added/removed/changed), and applies them to the given intermediate model.
+ *
+ * @param sourceModel The source model
+ * @param sourceTable The source table
+ * @param intermediateModel The intermediate model to apply the changes to
+ * @param intermediateTable The table from the intermediate model corresponding to the source table
+ * @param targetModel The target model
+ * @param targetTable The target table
+ * @return The changes
+ */
+ protected List checkForPrimaryKeyChanges(Database sourceModel,
+ Table sourceTable,
+ Database intermediateModel,
+ Table intermediateTable,
+ Database targetModel,
+ Table targetTable)
+ {
+ List changes = new ArrayList();
Column[] sourcePK = sourceTable.getPrimaryKeyColumns();
+ Column[] curPK = intermediateTable.getPrimaryKeyColumns();
Column[] targetPK = targetTable.getPrimaryKeyColumns();
- if ((sourcePK.length == 0) && (targetPK.length > 0))
+ if ((curPK.length == 0) && (targetPK.length > 0))
{
if (_log.isInfoEnabled())
{
- _log.info("A primary key needs to be added to the table " + sourceTable.getName());
+ _log.info("A primary key needs to be added to the table " + intermediateTable.getName());
}
- // we have to use the target table here because the primary key might
- // reference a new column
- changes.add(new AddPrimaryKeyChange(targetTable, targetPK));
+
+ AddPrimaryKeyChange change = new AddPrimaryKeyChange(intermediateTable.getName(), getIntermediateColumnNamesFor(targetPK, intermediateTable));
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
- else if ((targetPK.length == 0) && (sourcePK.length > 0))
+ else if ((targetPK.length == 0) && (curPK.length > 0))
{
if (_log.isInfoEnabled())
{
- _log.info("The primary key needs to be removed from the table " + sourceTable.getName());
+ _log.info("The primary key needs to be removed from the table " + intermediateTable.getName());
}
- changes.add(new RemovePrimaryKeyChange(sourceTable, sourcePK));
+
+ RemovePrimaryKeyChange change = new RemovePrimaryKeyChange(intermediateTable.getName());
+
+ changes.add(change);
+ change.apply(intermediateModel, _caseSensitive);
}
- else if ((sourcePK.length > 0) && (targetPK.length > 0))
+ else
{
boolean changePK = false;
- if (sourcePK.length != targetPK.length)
+ if ((curPK.length != targetPK.length) || (!_canDropPrimaryKeyColumns && sourcePK.length > targetPK.length))
{
changePK = true;
}
- else
+ else if ((curPK.length > 0) && (targetPK.length > 0))
{
- for (int pkColumnIdx = 0; (pkColumnIdx < sourcePK.length) && !changePK; pkColumnIdx++)
+ for (int pkColumnIdx = 0; (pkColumnIdx < curPK.length) && !changePK; pkColumnIdx++)
{
- if ((_caseSensitive && !sourcePK[pkColumnIdx].getName().equals(targetPK[pkColumnIdx].getName())) ||
- (!_caseSensitive && !sourcePK[pkColumnIdx].getName().equalsIgnoreCase(targetPK[pkColumnIdx].getName())))
+ if (!StringUtils.equals(curPK[pkColumnIdx].getName(), targetPK[pkColumnIdx].getName(), _caseSensitive))
{
changePK = true;
}
@@ -295,101 +798,66 @@
{
if (_log.isInfoEnabled())
{
- _log.info("The primary key of table " + sourceTable.getName() + " needs to be changed");
- }
- changes.add(new PrimaryKeyChange(sourceTable, targetPK));
- }
- }
-
- HashMap columnPosChanges = new HashMap();
-
- for (int columnIdx = 0; columnIdx < sourceTable.getColumnCount(); columnIdx++)
- {
- Column sourceColumn = sourceTable.getColumn(columnIdx);
- Column targetColumn = targetTable.findColumn(sourceColumn.getName(), _caseSensitive);
-
- if (targetColumn == null)
- {
- if (_log.isInfoEnabled())
- {
- _log.info("Column " + sourceColumn.getName() + " needs to be removed from table " + sourceTable.getName());
+ _log.info("The primary key of table " + intermediateTable.getName() + " needs to be changed");
}
- changes.add(new RemoveColumnChange(sourceTable, sourceColumn));
- }
- else
- {
- int targetColumnIdx = targetTable.getColumnIndex(targetColumn);
-
- if (targetColumnIdx != columnIdx)
+ if (_generatePrimaryKeyChanges)
{
- columnPosChanges.put(sourceColumn, new Integer(targetColumnIdx));
+ PrimaryKeyChange change = new PrimaryKeyChange(intermediateTable.getName(),
+ getIntermediateColumnNamesFor(targetPK, intermediateTable));
+
+ changes.add(change);
+ change.apply(intermediateModel, changePK);
+ }
+ else
+ {
+ RemovePrimaryKeyChange removePKChange = new RemovePrimaryKeyChange(intermediateTable.getName());
+ AddPrimaryKeyChange addPKChange = new AddPrimaryKeyChange(intermediateTable.getName(),
+ getIntermediateColumnNamesFor(targetPK, intermediateTable));
+
+ changes.add(removePKChange);
+ changes.add(addPKChange);
+ removePKChange.apply(intermediateModel, _caseSensitive);
+ addPKChange.apply(intermediateModel, _caseSensitive);
}
}
}
- if (!columnPosChanges.isEmpty())
- {
- changes.add(new ColumnOrderChange(sourceTable, columnPosChanges));
- }
-
return changes;
}
/**
- * Compares the two columns and returns the changes necessary to create the second
- * column from the first one.
+ * Compares the two columns and returns the change necessary to create the second
+ * column from the first one if they differe.
*
* @param sourceTable The source table which contains the source column
* @param sourceColumn The source column
* @param targetTable The target table which contains the target column
* @param targetColumn The target column
- * @return The changes
+ * @return The change or <code>null</code> if the columns are the same
*/
- public List compareColumns(Table sourceTable,
- Column sourceColumn,
- Table targetTable,
- Column targetColumn)
+ protected ColumnDefinitionChange compareColumns(Table sourceTable,
+ Column sourceColumn,
+ Table targetTable,
+ Column targetColumn)
{
- ArrayList changes = new ArrayList();
-
- if (_platformInfo.getTargetJdbcType(targetColumn.getTypeCode()) != sourceColumn.getTypeCode())
- {
- changes.add(new ColumnDataTypeChange(sourceTable, sourceColumn, targetColumn.getTypeCode()));
- }
-
- boolean sizeMatters = _platformInfo.hasSize(sourceColumn.getTypeCode());
- boolean scaleMatters = _platformInfo.hasPrecisionAndScale(sourceColumn.getTypeCode());
-
- if (sizeMatters &&
- !StringUtils.equals(sourceColumn.getSize(), targetColumn.getSize()))
- {
- changes.add(new ColumnSizeChange(sourceTable, sourceColumn, targetColumn.getSizeAsInt(), targetColumn.getScale()));
- }
- else if (scaleMatters &&
- (!StringUtils.equals(sourceColumn.getSize(), targetColumn.getSize()) ||
- (sourceColumn.getScale() != targetColumn.getScale())))
+ if (ColumnDefinitionChange.isChanged(getPlatformInfo(), sourceColumn, targetColumn))
{
- changes.add(new ColumnSizeChange(sourceTable, sourceColumn, targetColumn.getSizeAsInt(), targetColumn.getScale()));
+ Column newColumnDef = _cloneHelper.clone(sourceColumn, true);
+ int targetTypeCode = _platformInfo.getTargetJdbcType(targetColumn.getTypeCode());
+ boolean sizeMatters = _platformInfo.hasSize(targetTypeCode);
+ boolean scaleMatters = _platformInfo.hasPrecisionAndScale(targetTypeCode);
+
+ newColumnDef.setTypeCode(targetColumn.getTypeCode());
+ newColumnDef.setSize(sizeMatters || scaleMatters ? targetColumn.getSize() : null);
+ newColumnDef.setAutoIncrement(targetColumn.isAutoIncrement());
+ newColumnDef.setRequired(targetColumn.isRequired());
+ newColumnDef.setDescription(targetColumn.getDescription());
+ newColumnDef.setDefaultValue(targetColumn.getDefaultValue());
+ return new ColumnDefinitionChange(sourceTable.getName(), sourceColumn.getName(), newColumnDef);
}
-
- Object sourceDefaultValue = sourceColumn.getParsedDefaultValue();
- Object targetDefaultValue = targetColumn.getParsedDefaultValue();
-
- if (((sourceDefaultValue == null) && (targetDefaultValue != null)) ||
- ((sourceDefaultValue != null) && !sourceDefaultValue.equals(targetDefaultValue)))
- {
- changes.add(new ColumnDefaultValueChange(sourceTable, sourceColumn, targetColumn.getDefaultValue()));
- }
-
- if (sourceColumn.isRequired() != targetColumn.isRequired())
+ else
{
- changes.add(new ColumnRequiredChange(sourceTable, sourceColumn));
+ return null;
}
- if (sourceColumn.isAutoIncrement() != targetColumn.isAutoIncrement())
- {
- changes.add(new ColumnAutoIncrementChange(sourceTable, sourceColumn));
- }
-
- return changes;
}
/**
@@ -403,7 +871,7 @@
* @param fk The original foreign key
* @return The corresponding foreign key if found
*/
- private ForeignKey findCorrespondingForeignKey(Table table, ForeignKey fk)
+ protected ForeignKey findCorrespondingForeignKey(Table table, ForeignKey fk)
{
for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++)
{
@@ -428,7 +896,7 @@
* @param index The original index
* @return The corresponding index if found
*/
- private Index findCorrespondingIndex(Table table, Index index)
+ protected Index findCorrespondingIndex(Table table, Index index)
{
for (int indexIdx = 0; indexIdx < table.getIndexCount(); indexIdx++)
{
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/Pair.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/Pair.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/Pair.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/Pair.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,65 @@
+package org.apache.ddlutils.alteration;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * Represents a pair of objects.
+ *
+ * @version $Revision: $
+ */
+public class Pair
+{
+ /** The first object. */
+ private final Object _firstObj;
+ /** The first object. */
+ private final Object _secondObj;
+
+ /**
+ * Creates a pair object.
+ *
+ * @param firstObj The first object
+ * @param secondObj The second object
+ */
+ public Pair(Object firstObj, Object secondObj)
+ {
+ _firstObj = firstObj;
+ _secondObj = secondObj;
+ }
+
+ /**
+ * Returns the first object of the pair.
+ *
+ * @return The first object
+ */
+ public Object getFirst()
+ {
+ return _firstObj;
+ }
+
+ /**
+ * Returns the second object of the pair.
+ *
+ * @return The second object
+ */
+ public Object getSecond()
+ {
+ return _secondObj;
+ }
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/PrimaryKeyChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/PrimaryKeyChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/PrimaryKeyChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/PrimaryKeyChange.java Mon Dec 10 00:20:47 2007
@@ -30,40 +30,27 @@
*/
public class PrimaryKeyChange extends TableChangeImplBase
{
- /** The columns making up the original primary key. */
- private Column[] _oldPrimaryKeyColumns;
- /** The columns making up the new primary key. */
- private Column[] _newPrimaryKeyColumns;
+ /** The names of the columns making up the new primary key. */
+ private String[] _newPrimaryKeyColumns;
/**
* Creates a new change object.
*
- * @param table The table whose primary key is to be changed
- * @param newPrimaryKeyColumns The columns making up the new primary key
+ * @param tableName The name of the table whose primary key is to be changed
+ * @param newPrimaryKeyColumns The names of the columns making up the new primary key
*/
- public PrimaryKeyChange(Table table, Column[] newPrimaryKeyColumns)
+ public PrimaryKeyChange(String tableName, String[] newPrimaryKeyColumns)
{
- super(table);
- _oldPrimaryKeyColumns = table.getPrimaryKeyColumns();
+ super(tableName);
_newPrimaryKeyColumns = newPrimaryKeyColumns;
}
/**
- * Returns the columns making up the original primary key.
+ * Returns the names of the columns making up the new primary key.
*
- * @return The columns
+ * @return The column names
*/
- public Column[] getOldPrimaryKeyColumns()
- {
- return _oldPrimaryKeyColumns;
- }
-
- /**
- * Returns the columns making up the new primary key.
- *
- * @return The columns
- */
- public Column[] getNewPrimaryKeyColumns()
+ public String[] getNewPrimaryKeyColumns()
{
return _newPrimaryKeyColumns;
}
@@ -73,17 +60,16 @@
*/
public void apply(Database model, boolean caseSensitive)
{
- Table table = findChangedTable(model, caseSensitive);
+ Table table = findChangedTable(model, caseSensitive);
+ Column[] pkCols = table.getPrimaryKeyColumns();
- for (int idx = 0; idx < _oldPrimaryKeyColumns.length; idx++)
+ for (int idx = 0; idx < pkCols.length; idx++)
{
- Column column = table.findColumn(_oldPrimaryKeyColumns[idx].getName(), caseSensitive);
-
- column.setPrimaryKey(false);
+ pkCols[idx].setPrimaryKey(false);
}
for (int idx = 0; idx < _newPrimaryKeyColumns.length; idx++)
{
- Column column = table.findColumn(_newPrimaryKeyColumns[idx].getName(), caseSensitive);
+ Column column = table.findColumn(_newPrimaryKeyColumns[idx], caseSensitive);
column.setPrimaryKey(true);
}
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RecreateTableChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RecreateTableChange.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RecreateTableChange.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RecreateTableChange.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,103 @@
+package org.apache.ddlutils.alteration;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import java.util.List;
+
+import org.apache.ddlutils.model.CloneHelper;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+
+/**
+ * Represents the recreation of a table, i.e. creating a temporary table using the target table definition,
+ * copying the data from the original table into this temporary table, dropping the original table and
+ * finally renaming the temporary table to the final table. This change is only created by the model
+ * comparator if the table definition change predicate flags a table change as unsupported.
+ *
+ * @version $Revision: $
+ */
+public class RecreateTableChange extends TableChangeImplBase
+{
+ /** The target table definition. */
+ private Table _targetTable;
+ /** The original table changes, one of which is unsupported by the current platform. */
+ private List _originalChanges;
+
+ /**
+ * Creates a new change object for recreating a table. This change is used to specify that a table needs
+ * to be dropped and then re-created (with changes). In the standard model comparison algorithm, it will
+ * replace all direct changes to the table's columns (i.e. foreign key and index changes are unaffected).
+ *
+ * @param tableName The name of the table
+ * @param targetTable The table as it should be; note that the change object will keep a reference
+ * to this table which means that it should not be changed after creating this
+ * change object
+ * @param originalChanges The original changes that this change object replaces
+ */
+ public RecreateTableChange(String tableName, Table targetTable, List originalChanges)
+ {
+ super(tableName);
+ _targetTable = targetTable;
+ _originalChanges = originalChanges;
+ }
+
+ /**
+ * Returns the original table changes, one of which is unsupported by the current platform.
+ *
+ * @return The table changes
+ */
+ public List getOriginalChanges()
+ {
+ return _originalChanges;
+ }
+
+ /**
+ * Returns the target table definition. Due to when an object of this kind is created in the comparison
+ * process, this table object will not have any foreign keys pointing to or from it, i.e. it is
+ * independent of any model.
+ *
+ * @return The table definition
+ */
+ public Table getTargetTable()
+ {
+ return _targetTable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void apply(Database database, boolean caseSensitive)
+ {
+ // we only need to replace the table in the model, as there can't be a
+ // foreign key from or to it when these kind of changes are created
+ for (int tableIdx = 0; tableIdx < database.getTableCount(); tableIdx++)
+ {
+ Table curTable = database.getTable(tableIdx);
+
+ if ((caseSensitive && curTable.getName().equals(getChangedTable())) ||
+ (!caseSensitive && curTable.getName().equalsIgnoreCase(getChangedTable())))
+ {
+ database.removeTable(tableIdx);
+ database.addTable(tableIdx, new CloneHelper().clone(_targetTable, true, false, database, caseSensitive));
+ break;
+ }
+ }
+ }
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveColumnChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveColumnChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveColumnChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveColumnChange.java Mon Dec 10 00:20:47 2007
@@ -19,9 +19,7 @@
* under the License.
*/
-import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
-import org.apache.ddlutils.model.Table;
/**
* Represents the removal of a column from a table.
@@ -33,12 +31,12 @@
/**
* Creates a new change object.
*
- * @param table The table to remove the column from
- * @param column The column
+ * @param tableName The name of the table to remove the column from
+ * @param columnName The column's name
*/
- public RemoveColumnChange(Table table, Column column)
+ public RemoveColumnChange(String tableName, String columnName)
{
- super(table, column);
+ super(tableName, columnName);
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveForeignKeyChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveForeignKeyChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveForeignKeyChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveForeignKeyChange.java Mon Dec 10 00:20:47 2007
@@ -21,7 +21,6 @@
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
-import org.apache.ddlutils.model.Table;
/**
* Represents the removal of a foreign key from a table. Note that for
@@ -35,12 +34,12 @@
/**
* Creates a new change object.
*
- * @param table The table to remove the foreign key from
+ * @param tableName The name of the table to remove the foreign key from
* @param foreignKey The foreign key
*/
- public RemoveForeignKeyChange(Table table, ForeignKey foreignKey)
+ public RemoveForeignKeyChange(String tableName, ForeignKey foreignKey)
{
- super(table, foreignKey);
+ super(tableName, foreignKey);
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveIndexChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveIndexChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveIndexChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveIndexChange.java Mon Dec 10 00:20:47 2007
@@ -21,7 +21,6 @@
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Index;
-import org.apache.ddlutils.model.Table;
/**
* Represents the removal of an index from a table.
@@ -33,12 +32,12 @@
/**
* Creates a new change object.
*
- * @param table The table to remove the index from
- * @param index The index
+ * @param tableName The name of the table to remove the index from
+ * @param index The index
*/
- public RemoveIndexChange(Table table, Index index)
+ public RemoveIndexChange(String tableName, Index index)
{
- super(table, index);
+ super(tableName, index);
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemovePrimaryKeyChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemovePrimaryKeyChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemovePrimaryKeyChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemovePrimaryKeyChange.java Mon Dec 10 00:20:47 2007
@@ -30,29 +30,14 @@
*/
public class RemovePrimaryKeyChange extends TableChangeImplBase
{
- /** The columns making up the primary key. */
- private Column[] _primaryKeyColumns;
-
/**
* Creates a new change object.
*
- * @param table The table to remove the primary key from
- * @param primaryKeyColumns The columns making up the primary key
+ * @param tableName The name of he table to remove the primary key from
*/
- public RemovePrimaryKeyChange(Table table, Column[] primaryKeyColumns)
+ public RemovePrimaryKeyChange(String tableName)
{
- super(table);
- _primaryKeyColumns = primaryKeyColumns;
- }
-
- /**
- * Returns the primary key columns making up the primary key.
- *
- * @return The primary key columns
- */
- public Column[] getPrimaryKeyColumns()
- {
- return _primaryKeyColumns;
+ super(tableName);
}
/**
@@ -60,13 +45,12 @@
*/
public void apply(Database model, boolean caseSensitive)
{
- Table table = findChangedTable(model, caseSensitive);
+ Table table = findChangedTable(model, caseSensitive);
+ Column[] pkCols = table.getPrimaryKeyColumns();
- for (int idx = 0; idx < _primaryKeyColumns.length; idx++)
+ for (int idx = 0; idx < pkCols.length; idx++)
{
- Column column = table.findColumn(_primaryKeyColumns[idx].getName(), caseSensitive);
-
- column.setPrimaryKey(false);
+ pkCols[idx].setPrimaryKey(false);
}
}
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTableChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTableChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTableChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTableChange.java Mon Dec 10 00:20:47 2007
@@ -25,6 +25,7 @@
/**
* Represents the removal of a table from a model.
*
+ * TODO: this should be a model change
* @version $Revision: $
*/
public class RemoveTableChange extends TableChangeImplBase
@@ -32,11 +33,11 @@
/**
* Creates a new change object.
*
- * @param table The table
+ * @param tableName The name of the table to be removed
*/
- public RemoveTableChange(Table table)
+ public RemoveTableChange(String tableName)
{
- super(table);
+ super(tableName);
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChange.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChange.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChange.java Mon Dec 10 00:20:47 2007
@@ -30,11 +30,11 @@
public interface TableChange extends ModelChange
{
/**
- * Returns the affected table from the original model.
+ * Returns the name of the affected table from the original model.
*
- * @return The affected table
+ * @return The name of the affected table
*/
- public Table getChangedTable();
+ public String getChangedTable();
/**
* Finds the table object corresponding to the changed table in the given database model.
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChangeImplBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChangeImplBase.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChangeImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableChangeImplBase.java Mon Dec 10 00:20:47 2007
@@ -29,25 +29,25 @@
*/
public abstract class TableChangeImplBase implements TableChange
{
- /** The affected table. */
- private Table _table;
+ /** The name of the affected table. */
+ private String _tableName;
/**
* Creates a new change object.
*
- * @param table The table
+ * @param tableName The table's name
*/
- public TableChangeImplBase(Table table)
+ public TableChangeImplBase(String tableName)
{
- _table = table;
+ _tableName = tableName;
}
/**
* {@inheritDoc}
*/
- public Table getChangedTable()
+ public String getChangedTable()
{
- return _table;
+ return _tableName;
}
/**
@@ -55,6 +55,6 @@
*/
public Table findChangedTable(Database model, boolean caseSensitive)
{
- return model.findTable(_table.getName(), caseSensitive);
+ return model.findTable(_tableName, caseSensitive);
}
}
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableDefinitionChangesPredicate.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableDefinitionChangesPredicate.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableDefinitionChangesPredicate.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/TableDefinitionChangesPredicate.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,45 @@
+package org.apache.ddlutils.alteration;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+import java.util.List;
+
+import org.apache.ddlutils.model.Table;
+
+/**
+ * Defines a predicate that allows platforms to state whether all of the given table definition
+ * changes (i.e. column changes and primary key changes) are supported by the platform or not.
+ *
+ * @version $Revision: $
+ */
+public interface TableDefinitionChangesPredicate
+{
+ /**
+ * Evaluates the given list of table changes and determines whether they are supported.
+ *
+ * @param intermediateTable The current table object which has certain non-table-definition
+ * changes already applied (those that would come before the give
+ * list of changes in the result of
+ * {@link ModelComparator#compare(org.apache.ddlutils.model.Database, org.apache.ddlutils.model.Database)}
+ * @param changes The non-empty list of changes
+ * @return <code>true</code> if the current plaform supports them
+ */
+ public boolean areSupported(Table intermediateTable, List changes);
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java Mon Dec 10 00:20:47 2007
@@ -26,8 +26,8 @@
import org.apache.commons.lang.enums.ValuedEnum;
/**
- * Represents the different cascade actions for {@link ForeignKey#onDelete} and
- * {@link ForeignKey#onUdate}.
+ * Represents the different cascade actions for the <code>onDelete</code> and
+ * <code>onUpdate</code> properties of {@link ForeignKey}.
*
* @version $Revision: $
*/
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CloneHelper.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CloneHelper.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CloneHelper.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CloneHelper.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,221 @@
+package org.apache.ddlutils.model;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+/**
+ * Helper class that provides cloning of model elements.
+ *
+ * @version $Revision: $
+ */
+public class CloneHelper
+{
+ /**
+ * Returns a deep clone of the given model object, including all tables, foreign keys, indexes etc.
+ *
+ * @param source The source model
+ * @return The clone
+ */
+ public Database clone(Database source)
+ {
+ Database result = new Database();
+
+ result.setName(source.getName());
+ result.setIdMethod(source.getIdMethod());
+ result.setVersion(source.getVersion());
+
+ for (int tableIdx = 0; tableIdx < source.getTableCount(); tableIdx++)
+ {
+ Table sourceTable = source.getTable(tableIdx);
+
+ result.addTable(clone(sourceTable, true, false, result, true));
+ }
+ for (int tableIdx = 0; tableIdx < source.getTableCount(); tableIdx++)
+ {
+ Table sourceTable = source.getTable(tableIdx);
+ Table clonedTable = result.getTable(tableIdx);
+
+ for (int fkIdx = 0; fkIdx < sourceTable.getForeignKeyCount(); fkIdx++)
+ {
+ ForeignKey sourceFk = sourceTable.getForeignKey(fkIdx);
+
+ clonedTable.addForeignKey(clone(sourceFk, clonedTable, result, true));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given table.
+ *
+ * @param source The source table
+ * @param cloneIndexes Whether to clone indexes; if <code>false</code> then the clone will
+ * not have any indexes
+ * @param cloneForeignKeys Whether to clone foreign kets; if <code>false</code> then the clone
+ * will not have any foreign keys
+ * @param targetModel The target model, can be <code>null</code> if
+ * <code>cloneForeignKeys=false</code>
+ * @param caseSensitive Whether comparison is case sensitive (for cloning foreign keys)
+ * @return The clone
+ */
+ public Table clone(Table source, boolean cloneIndexes, boolean cloneForeignKeys, Database targetModel, boolean caseSensitive)
+ {
+ Table result = new Table();
+
+ result.setCatalog(source.getCatalog());
+ result.setSchema(source.getSchema());
+ result.setName(source.getName());
+ result.setType(source.getType());
+
+ for (int colIdx = 0; colIdx < source.getColumnCount(); colIdx++)
+ {
+ result.addColumn(clone(source.getColumn(colIdx), true));
+ }
+ if (cloneIndexes)
+ {
+ for (int indexIdx = 0; indexIdx < source.getIndexCount(); indexIdx++)
+ {
+ result.addIndex(clone(source.getIndex(indexIdx), result, true));
+ }
+ }
+ if (cloneForeignKeys)
+ {
+ for (int fkIdx = 0; fkIdx < source.getForeignKeyCount(); fkIdx++)
+ {
+ result.addForeignKey(clone(source.getForeignKey(fkIdx), result, targetModel, caseSensitive));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given source column.
+ *
+ * @param source The source column
+ * @param clonePrimaryKeyStatus Whether to clone the column's primary key status; if <code>false</code>
+ * then the clone will not be a primary key column
+ * @return The clone
+ */
+ public Column clone(Column source, boolean clonePrimaryKeyStatus)
+ {
+ Column result = new Column();
+
+ result.setName(source.getName());
+ result.setJavaName(source.getJavaName());
+ result.setPrimaryKey(clonePrimaryKeyStatus ? source.isPrimaryKey() : false);
+ result.setRequired(source.isRequired());
+ result.setAutoIncrement(source.isAutoIncrement());
+ result.setTypeCode(source.getTypeCode());
+ result.setSize(source.getSize());
+ result.setDefaultValue(source.getDefaultValue());
+
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given source index.
+ *
+ * @param source The source index
+ * @param targetTable The table whose columns shall be used by the clone
+ * @param caseSensitive Whether comparison is case sensitive (for finding the columns
+ * in the target table)
+ * @return The clone
+ */
+ public Index clone(Index source, Table targetTable, boolean caseSensitive)
+ {
+ Index result = (source.isUnique() ? (Index)new UniqueIndex() : (Index)new NonUniqueIndex());
+
+ result.setName(source.getName());
+ for (int colIdx = 0; colIdx < source.getColumnCount(); colIdx++)
+ {
+ IndexColumn column = source.getColumn(colIdx);
+
+ result.addColumn(clone(column, targetTable, caseSensitive));
+ }
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given index column.
+ *
+ * @param source The source index column
+ * @param targetTable The table containing the column to be used by the clone
+ * @param caseSensitive Whether comparison is case sensitive (for finding the columns
+ * in the target table)
+ * @return The clone
+ */
+ public IndexColumn clone(IndexColumn source, Table targetTable, boolean caseSensitive)
+ {
+ IndexColumn result = new IndexColumn();
+
+ result.setColumn(targetTable.findColumn(source.getName(), caseSensitive));
+ result.setOrdinalPosition(source.getOrdinalPosition());
+ result.setSize(source.getSize());
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given source foreign key.
+ *
+ * @param source The source foreign key
+ * @param owningTable The table owning the source foreign key
+ * @param targetModel The target model containing the tables that the clone shall link
+ * @param caseSensitive Whether comparison is case sensitive (for finding the columns
+ * in the target model)
+ * @return The clone
+ */
+ public ForeignKey clone(ForeignKey source, Table owningTable, Database targetModel, boolean caseSensitive)
+ {
+ ForeignKey result = new ForeignKey();
+ Table foreignTable = targetModel.findTable(source.getForeignTableName(), caseSensitive);
+
+ result.setName(source.getName());
+ result.setForeignTable(foreignTable);
+ result.setAutoIndexPresent(source.isAutoIndexPresent());
+
+ for (int refIdx = 0; refIdx < source.getReferenceCount(); refIdx++)
+ {
+ Reference ref = source.getReference(refIdx);
+
+ result.addReference(clone(ref, owningTable, foreignTable, caseSensitive));
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns a clone of the given source reference.
+ *
+ * @param source The source reference
+ * @param localTable The table containing the local column to be used by the reference
+ * @param foreignTable The table containing the foreign column to be used by the reference
+ * @param caseSensitive Whether comparison is case sensitive (for finding the columns
+ * in the tables)
+ * @return The clone
+ */
+ public Reference clone(Reference source, Table localTable, Table foreignTable, boolean caseSensitive)
+ {
+ Reference result = new Reference();
+
+ result.setLocalColumn(localTable.findColumn(source.getLocalColumnName(), caseSensitive));
+ result.setForeignColumn(foreignTable.findColumn(source.getForeignColumnName(), caseSensitive));
+ return result;
+ }
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Column.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Column.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Column.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Column.java Mon Dec 10 00:20:47 2007
@@ -36,7 +36,7 @@
*
* @version $Revision$
*/
-public class Column implements Cloneable, Serializable
+public class Column implements Serializable
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -6226348998874210093L;
@@ -478,29 +478,6 @@
public void setDefaultValue(String defaultValue)
{
_defaultValue = defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- Column result = (Column)super.clone();
-
- result._name = _name;
- result._javaName = _javaName;
- result._primaryKey = _primaryKey;
- result._required = _required;
- result._autoIncrement = _autoIncrement;
- result._typeCode = _typeCode;
- result._type = _type;
- result._size = _size;
- result._defaultValue = _defaultValue;
- result._scale = _scale;
- result._size = _size;
- result._sizeAsInt = _sizeAsInt;
-
- return result;
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Database.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Database.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Database.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Database.java Mon Dec 10 00:20:47 2007
@@ -40,7 +40,7 @@
*
* @version $Revision$
*/
-public class Database implements Serializable, Cloneable
+public class Database implements Serializable
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -3160443396757573868L;
@@ -64,22 +64,32 @@
*/
public void mergeWith(Database otherDb) throws ModelException
{
- for (Iterator it = otherDb._tables.iterator(); it.hasNext();)
+ CloneHelper cloneHelper = new CloneHelper();
+
+ for (int tableIdx = 0; tableIdx < otherDb.getTableCount(); tableIdx++)
{
- Table table = (Table)it.next();
+ Table table = otherDb.getTable(tableIdx);
if (findTable(table.getName()) != null)
{
// TODO: It might make more sense to log a warning and overwrite the table (or merge them) ?
throw new ModelException("Cannot merge the models because table "+table.getName()+" already defined in this model");
}
- try
+ else
{
- addTable((Table)table.clone());
+ addTable(cloneHelper.clone(table, true, false, this, true));
}
- catch (CloneNotSupportedException ex)
+ }
+ for (int tableIdx = 0; tableIdx < otherDb.getTableCount(); tableIdx++)
+ {
+ Table otherTable = otherDb.getTable(tableIdx);
+ Table localTable = findTable(otherTable.getName());
+
+ for (int fkIdx = 0; fkIdx < otherTable.getForeignKeyCount(); fkIdx++)
{
- // won't happen
+ ForeignKey fk = otherTable.getForeignKey(fkIdx);
+
+ localTable.addForeignKey(cloneHelper.clone(fk, localTable, this, false));
}
}
}
@@ -292,7 +302,7 @@
}
if (namesOfProcessedColumns.contains(column.getName()))
{
- throw new ModelException("There are multiple column with the name "+column.getName()+" in the table "+curTable.getName());
+ throw new ModelException("There are multiple columns with the name "+column.getName()+" in the table "+curTable.getName());
}
namesOfProcessedColumns.add(column.getName());
@@ -526,21 +536,6 @@
public DynaBean createDynaBeanFor(String tableName, boolean caseSensitive) throws SqlDynaException
{
return getDynaClassCache().createNewInstance(findTable(tableName, caseSensitive));
- }
-
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- Database result = (Database)super.clone();
-
- result._name = _name;
- result._idMethod = _idMethod;
- result._version = _version;
- result._tables = (ArrayList)_tables.clone();
-
- return result;
}
/**