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 [3/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/model/ForeignKey.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java Mon Dec 10 00:20:47 2007
@@ -19,20 +19,24 @@
* under the License.
*/
+import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.apache.ddlutils.util.StringUtils;
/**
* Represents a database foreign key.
*
* @version $Revision$
*/
-public class ForeignKey implements Cloneable
+public class ForeignKey implements Serializable
{
+ /** Unique ID for serialization purposes. */
+ private static final long serialVersionUID = 7833254626253719913L;
/** The name of the foreign key, may be <code>null</code>. */
private String _name;
/** The target table. */
@@ -292,6 +296,28 @@
}
/**
+ * Determines whether this foreign key uses the indicated column as a local
+ * column in a reference. This method assumes that the caller checked
+ * already that the column is a column in the table owning this foreign key.
+ *
+ * @param columnName The name of the column to check
+ * @param caseSensitive Whether case matters when checking for the column's name
+ * @return <code>true</code> if a reference uses the column as a local
+ * column
+ */
+ public boolean hasLocalColumn(String columnName, boolean caseSensitive)
+ {
+ for (int idx = 0; idx < getReferenceCount(); idx++)
+ {
+ if (StringUtils.equals(columnName, getReference(idx).getLocalColumnName(), caseSensitive))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Determines whether this foreign key uses the given column as a foreign
* column in a reference.
*
@@ -310,9 +336,32 @@
}
return false;
}
+
+ /**
+ * Determines whether this foreign key uses the given column as a foreign
+ * column in a reference. This method assumes that the caller already checked
+ * whether this foreign key references the tale owning the indicate column.
+ *
+ * @param columnName The name of the column to check
+ * @param caseSensitive Whether case matters when checking for the column's name
+ * @return <code>true</code> if a reference uses the column as a foreign
+ * column
+ */
+ public boolean hasForeignColumn(String columnName, boolean caseSensitive)
+ {
+ for (int idx = 0; idx < getReferenceCount(); idx++)
+ {
+ if (StringUtils.equals(columnName, getReference(idx).getForeignColumnName(), caseSensitive))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
/**
- * Determines whether this foreign key has an auto-generated associated index.
+ * Determines whether this foreign key has an auto-generated associated index. Note that
+ * this is a hint for the platform and has no relevancy to the model itself.
*
* @return <code>true</code> if an auto-generated index exists
*/
@@ -322,32 +371,14 @@
}
/**
- * Specifies whether this foreign key has an auto-generated associated index.
+ * Specifies whether this foreign key has an auto-generated associated index. Note that
+ * this is a hint set by the model reader and has no relevancy to the model itself.
*
* @param autoIndexPresent <code>true</code> if an auto-generated index exists
*/
public void setAutoIndexPresent(boolean autoIndexPresent)
{
_autoIndexPresent = autoIndexPresent;
- }
-
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- ForeignKey result = (ForeignKey)super.clone();
-
- result._name = _name;
- result._foreignTableName = _foreignTableName;
- result._references = new ListOrderedSet();
-
- for (Iterator it = _references.iterator(); it.hasNext();)
- {
- result._references.add(((Reference)it.next()).clone());
- }
-
- return result;
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Index.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Index.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Index.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Index.java Mon Dec 10 00:20:47 2007
@@ -80,6 +80,15 @@
public boolean hasColumn(Column column);
/**
+ * Determines whether this index includes the indicated column.
+ *
+ * @param columnName The name of the column to check for
+ * @param caseSensitive Whether the case of the column name matters for the check
+ * @return <code>true</code> if the column is included in this index
+ */
+ public boolean hasColumn(String columnName, boolean caseSensitive);
+
+ /**
* Adds a column that makes up this index.
*
* @param column The column to add
@@ -107,6 +116,14 @@
* @throws CloneNotSupportedException If the cloning did fail
*/
public Object clone() throws CloneNotSupportedException;
+
+ /**
+ * Returns a clone of this index object. This is essentially the same method as
+ * {@link #clone()}, except that it does not throw a checked exception.
+ *
+ * @return The clone
+ */
+ public Index getClone() throws ModelException;
/**
* Compares this index to the given one while ignoring the case of identifiers.
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexColumn.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexColumn.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexColumn.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexColumn.java Mon Dec 10 00:20:47 2007
@@ -29,7 +29,7 @@
*
* @version $Revision$
*/
-public class IndexColumn implements Cloneable, Serializable
+public class IndexColumn implements Serializable
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -5009366896427504739L;
@@ -43,8 +43,6 @@
/** The size of the column in the index. */
protected String _size;
- // TODO: It might be useful if the referenced column is directly acessible here ?
-
/**
* Creates a new index column object.
*/
@@ -154,19 +152,7 @@
{
_size = size;
}
-
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- IndexColumn result = (IndexColumn)super.clone();
-
- result._name = _name;
- result._size = _size;
- return result;
- }
-
+
/**
* {@inheritDoc}
*/
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexImplBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexImplBase.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexImplBase.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/IndexImplBase.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,153 @@
+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.
+ */
+
+import java.util.ArrayList;
+
+import org.apache.ddlutils.util.StringUtils;
+
+/**
+ * Base class for indexes.
+ *
+ * @version $Revision: $
+ */
+public abstract class IndexImplBase implements Index
+{
+ /** The name of the index. */
+ protected String _name;
+ /** The columns making up the index. */
+ protected ArrayList _columns = new ArrayList();
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getName()
+ {
+ return _name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setName(String name)
+ {
+ _name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getColumnCount()
+ {
+ return _columns.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IndexColumn getColumn(int idx)
+ {
+ return (IndexColumn)_columns.get(idx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public IndexColumn[] getColumns()
+ {
+ return (IndexColumn[])_columns.toArray(new IndexColumn[_columns.size()]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasColumn(Column column)
+ {
+ for (int idx = 0; idx < _columns.size(); idx++)
+ {
+ IndexColumn curColumn = getColumn(idx);
+
+ if (column.equals(curColumn.getColumn()))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasColumn(String columnName, boolean caseSensitive)
+ {
+ for (int idx = 0; idx < _columns.size(); idx++)
+ {
+ IndexColumn curColumn = getColumn(idx);
+
+ if (StringUtils.equals(columnName, curColumn.getName(), caseSensitive))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addColumn(IndexColumn column)
+ {
+ if (column != null)
+ {
+ for (int idx = 0; idx < _columns.size(); idx++)
+ {
+ IndexColumn curColumn = getColumn(idx);
+
+ if (curColumn.getOrdinalPosition() > column.getOrdinalPosition())
+ {
+ _columns.add(idx, column);
+ return;
+ }
+ }
+ _columns.add(column);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeColumn(IndexColumn column)
+ {
+ _columns.remove(column);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeColumn(int idx)
+ {
+ _columns.remove(idx);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public abstract Object clone() throws CloneNotSupportedException;
+}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/NonUniqueIndex.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/NonUniqueIndex.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/NonUniqueIndex.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/NonUniqueIndex.java Mon Dec 10 00:20:47 2007
@@ -29,7 +29,7 @@
*
* @version $Revision: 289996 $
*/
-public class NonUniqueIndex extends IndexImpBase
+public class NonUniqueIndex extends IndexImplBase
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -3591499395114850301L;
@@ -46,6 +46,14 @@
* {@inheritDoc}
*/
public Object clone() throws CloneNotSupportedException
+ {
+ return getClone();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Index getClone() throws ModelException
{
NonUniqueIndex result = new NonUniqueIndex();
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java Mon Dec 10 00:20:47 2007
@@ -29,7 +29,7 @@
*
* @version $Revision$
*/
-public class Reference implements Cloneable, Serializable
+public class Reference implements Serializable
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = 6062467640266171664L;
@@ -175,19 +175,6 @@
_foreignColumn = null;
}
_foreignColumnName = foreignColumnName;
- }
-
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- Reference result = (Reference)super.clone();
-
- result._localColumnName = _localColumnName;
- result._foreignColumnName = _foreignColumnName;
-
- return result;
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java Mon Dec 10 00:20:47 2007
@@ -38,7 +38,7 @@
*
* @version $Revision$
*/
-public class Table implements Serializable, Cloneable
+public class Table implements Serializable
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -5541154961302342608L;
@@ -267,6 +267,16 @@
}
/**
+ * Removes all columns of this table. Note that this does not change
+ * indexes or foreign keys, so it might leave the table object in
+ * an illegal state.
+ */
+ public void removeAllColumns()
+ {
+ _columns.clear();
+ }
+
+ /**
* Removes the indicated column.
*
* @param idx The index of the column to remove
@@ -348,6 +358,14 @@
}
/**
+ * Removes all foreign keys.
+ */
+ public void removeAllForeignKeys()
+ {
+ _foreignKeys.clear();
+ }
+
+ /**
* Removes the given foreign key.
*
* @param foreignKey The foreign key to remove
@@ -708,6 +726,24 @@
}
/**
+ * Returns the names of the primary key columns of this table.
+ *
+ * @return The primary key column names
+ */
+ public String[] getPrimaryKeyColumnNames()
+ {
+ Column[] pkColumns = getPrimaryKeyColumns();
+ String[] names = new String[pkColumns.length];
+
+ for (int colIdx = 0; colIdx < pkColumns.length; colIdx++)
+ {
+ names[colIdx] = pkColumns[colIdx].getName();
+ }
+
+ return names;
+ }
+
+ /**
* Returns the auto increment columns in this table. If no incrementcolumns
* are found, it will return an empty array.
*
@@ -752,24 +788,6 @@
}
}
- /**
- * {@inheritDoc}
- */
- public Object clone() throws CloneNotSupportedException
- {
- Table result = (Table)super.clone();
-
- result._catalog = _catalog;
- result._schema = _schema;
- result._name = _name;
- result._type = _type;
- result._columns = (ArrayList)_columns.clone();
- result._foreignKeys = (ArrayList)_foreignKeys.clone();
- result._indices = (ArrayList)_indices.clone();
-
- return result;
- }
-
/**
* {@inheritDoc}
*/
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/UniqueIndex.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/UniqueIndex.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/UniqueIndex.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/UniqueIndex.java Mon Dec 10 00:20:47 2007
@@ -30,7 +30,7 @@
*
* @version $Revision$
*/
-public class UniqueIndex extends IndexImpBase
+public class UniqueIndex extends IndexImplBase
{
/** Unique ID for serialization purposes. */
private static final long serialVersionUID = -4097003126550294993L;
@@ -47,6 +47,14 @@
* {@inheritDoc}
*/
public Object clone() throws CloneNotSupportedException
+ {
+ return getClone();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Index getClone() throws ModelException
{
UniqueIndex result = new UniqueIndex();
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DefaultTableDefinitionChangesPredicate.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DefaultTableDefinitionChangesPredicate.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DefaultTableDefinitionChangesPredicate.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/DefaultTableDefinitionChangesPredicate.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,85 @@
+package org.apache.ddlutils.platform;
+
+/*
+ * 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.Iterator;
+import java.util.List;
+
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+import org.apache.ddlutils.model.Table;
+
+/**
+ * This is the default predicate for filtering supported table definition changes
+ * in the {@link ModelComparator}. It is also useful as the base class for platform
+ * specific implementations.
+ *
+ * @version $Revision: $
+ */
+public class DefaultTableDefinitionChangesPredicate implements TableDefinitionChangesPredicate
+{
+ /**
+ * {@inheritDoc}
+ */
+ public boolean areSupported(Table intermediateTable, List changes)
+ {
+ for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
+ {
+ TableChange change = (TableChange)changeIt.next();
+
+ if (!isSupported(intermediateTable, change))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Checks whether the given change is suppored.
+ *
+ * @param intermediateTable The current table to which this change would be applied
+ * @param change The table change
+ * @return <code>true</code> if the change is supported
+ */
+ protected boolean isSupported(Table intermediateTable, TableChange change)
+ {
+ if (change instanceof AddColumnChange)
+ {
+ AddColumnChange addColumnChange = (AddColumnChange)change;
+
+ return addColumnChange.isAtEnd() &&
+ (!addColumnChange.getNewColumn().isRequired() ||
+ (addColumnChange.getNewColumn().getDefaultValue() != null) ||
+ addColumnChange.getNewColumn().isAutoIncrement());
+ }
+ else if (change instanceof AddPrimaryKeyChange)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
\ No newline at end of file
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java Mon Dec 10 00:20:47 2007
@@ -663,7 +663,7 @@
{
Index index = table.getIndex(indexIdx);
- if ((mustBeUnique == index.isUnique()) && matches(index, columnNames) &&
+ if ((!mustBeUnique || index.isUnique()) && matches(index, columnNames) &&
isInternalForeignKeyIndex(metaData, table, fk, index))
{
fk.setAutoIndexPresent(true);
@@ -1065,10 +1065,11 @@
*/
protected void determineAutoIncrementFromResultSetMetaData(Table table, Column[] columnsToCheck) throws SQLException
{
- if (columnsToCheck == null || columnsToCheck.length == 0)
+ if ((columnsToCheck == null) || (columnsToCheck.length == 0))
{
return;
}
+
StringBuffer query = new StringBuffer();
query.append("SELECT ");
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java Mon Dec 10 00:20:47 2007
@@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
@@ -35,6 +36,8 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -50,10 +53,34 @@
import org.apache.ddlutils.DdlUtilsException;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddForeignKeyChange;
+import org.apache.ddlutils.alteration.AddIndexChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.AddTableChange;
+import org.apache.ddlutils.alteration.ColumnDefinitionChange;
+import org.apache.ddlutils.alteration.ColumnOrderChange;
+import org.apache.ddlutils.alteration.ForeignKeyChange;
+import org.apache.ddlutils.alteration.IndexChange;
+import org.apache.ddlutils.alteration.ModelChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.PrimaryKeyChange;
+import org.apache.ddlutils.alteration.RecreateTableChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.RemoveForeignKeyChange;
+import org.apache.ddlutils.alteration.RemoveIndexChange;
+import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
+import org.apache.ddlutils.alteration.RemoveTableChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
import org.apache.ddlutils.dynabean.SqlDynaClass;
import org.apache.ddlutils.dynabean.SqlDynaProperty;
+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.ModelException;
import org.apache.ddlutils.model.Table;
import org.apache.ddlutils.model.TypeMap;
import org.apache.ddlutils.util.Jdbc3Utils;
@@ -402,16 +429,15 @@
*/
public void createTables(Database model, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
{
- Connection connection = borrowConnection();
+ createModel(model, dropTablesFirst, continueOnError);
+ }
- try
- {
- createTables(connection, model, dropTablesFirst, continueOnError);
- }
- finally
- {
- returnConnection(connection);
- }
+ /**
+ * {@inheritDoc}
+ */
+ public void createTables(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ {
+ createModel(model, params, dropTablesFirst, continueOnError);
}
/**
@@ -419,9 +445,15 @@
*/
public void createTables(Connection connection, Database model, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
{
- String sql = getCreateTablesSql(model, dropTablesFirst, continueOnError);
+ createModel(connection, model, dropTablesFirst, continueOnError);
+ }
- evaluateBatch(connection, sql, continueOnError);
+ /**
+ * {@inheritDoc}
+ */
+ public void createTables(Connection connection, Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ {
+ createModel(connection, model, params, dropTablesFirst, continueOnError);
}
/**
@@ -429,33 +461,54 @@
*/
public String getCreateTablesSql(Database model, boolean dropTablesFirst, boolean continueOnError)
{
- String sql = null;
+ return getCreateTablesSql(model, dropTablesFirst, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getCreateTablesSql(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError)
+ {
+ return getCreateTablesSql(model, params, dropTablesFirst, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createModel(Database model, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ {
+ Connection connection = borrowConnection();
try
{
- StringWriter buffer = new StringWriter();
-
- getSqlBuilder().setWriter(buffer);
- getSqlBuilder().createTables(model, dropTablesFirst);
- sql = buffer.toString();
+ createModel(connection, model, dropTablesFirst, continueOnError);
}
- catch (IOException e)
+ finally
{
- // won't happen because we're using a string writer
+ returnConnection(connection);
}
- return sql;
}
/**
* {@inheritDoc}
*/
- public void createTables(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ public void createModel(Connection connection, Database model, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ {
+ String sql = getCreateModelSql(model, dropTablesFirst, continueOnError);
+
+ evaluateBatch(connection, sql, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createModel(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
{
Connection connection = borrowConnection();
try
{
- createTables(connection, model, params, dropTablesFirst, continueOnError);
+ createModel(connection, model, params, dropTablesFirst, continueOnError);
}
finally
{
@@ -466,9 +519,9 @@
/**
* {@inheritDoc}
*/
- public void createTables(Connection connection, Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
+ public void createModel(Connection connection, Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError) throws DatabaseOperationException
{
- String sql = getCreateTablesSql(model, params, dropTablesFirst, continueOnError);
+ String sql = getCreateModelSql(model, params, dropTablesFirst, continueOnError);
evaluateBatch(connection, sql, continueOnError);
}
@@ -476,7 +529,29 @@
/**
* {@inheritDoc}
*/
- public String getCreateTablesSql(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError)
+ public String getCreateModelSql(Database model, boolean dropTablesFirst, boolean continueOnError)
+ {
+ String sql = null;
+
+ try
+ {
+ StringWriter buffer = new StringWriter();
+
+ getSqlBuilder().setWriter(buffer);
+ getSqlBuilder().createTables(model, dropTablesFirst);
+ sql = buffer.toString();
+ }
+ catch (IOException e)
+ {
+ // won't happen because we're using a string writer
+ }
+ return sql;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getCreateModelSql(Database model, CreationParameters params, boolean dropTablesFirst, boolean continueOnError)
{
String sql = null;
@@ -496,15 +571,100 @@
}
/**
+ * Returns the model comparator to be used for this platform. This method is intendeded
+ * to be redefined by platforms that need to customize the model reader.
+ *
+ * @return The model comparator
+ */
+ protected ModelComparator getModelComparator()
+ {
+ return new ModelComparator(getPlatformInfo(),
+ getTableDefinitionChangesPredicate(),
+ isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Returns the predicate that defines which changes are supported by the platform.
+ *
+ * @return The predicate
+ */
+ protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+ {
+ return new DefaultTableDefinitionChangesPredicate();
+ }
+
+ /**
* {@inheritDoc}
*/
- public void alterTables(Database desiredDb, boolean continueOnError) throws DatabaseOperationException
+ public List getChanges(Database currentModel, Database desiredModel)
+ {
+ List changes = getModelComparator().compare(currentModel, desiredModel);
+
+ return sortChanges(changes);
+ }
+
+ /**
+ * Sorts the changes so that they can be executed by the database. E.g. tables need to be created before
+ * they can be referenced by foreign keys, indexes should be dropped before a table is dropped etc.
+ *
+ * @param changes The original changes
+ * @return The sorted changes - this can be the original list object or a new one
+ */
+ protected List sortChanges(List changes)
+ {
+ final Map typeOrder = new HashMap();
+
+ typeOrder.put(RemoveForeignKeyChange.class, new Integer(0));
+ typeOrder.put(RemoveIndexChange.class, new Integer(1));
+ typeOrder.put(RemoveTableChange.class, new Integer(2));
+ typeOrder.put(RecreateTableChange.class, new Integer(3));
+ typeOrder.put(RemovePrimaryKeyChange.class, new Integer(3));
+ typeOrder.put(RemoveColumnChange.class, new Integer(4));
+ typeOrder.put(ColumnDefinitionChange.class, new Integer(5));
+ typeOrder.put(ColumnOrderChange.class, new Integer(5));
+ typeOrder.put(AddColumnChange.class, new Integer(5));
+ typeOrder.put(PrimaryKeyChange.class, new Integer(5));
+ typeOrder.put(AddPrimaryKeyChange.class, new Integer(6));
+ typeOrder.put(AddTableChange.class, new Integer(7));
+ typeOrder.put(AddIndexChange.class, new Integer(8));
+ typeOrder.put(AddForeignKeyChange.class, new Integer(9));
+
+ Collections.sort(changes, new Comparator()
+ {
+ public int compare(Object objA, Object objB)
+ {
+ Integer orderValueA = (Integer)typeOrder.get(objA.getClass());
+ Integer orderValueB = (Integer)typeOrder.get(objB.getClass());
+
+ if (orderValueA == null)
+ {
+ return (orderValueB == null ? 0 : 1);
+ }
+ else if (orderValueB == null)
+ {
+ return -1;
+ }
+ else
+ {
+ return orderValueA.compareTo(orderValueB);
+ }
+ }
+ });
+ return changes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void alterTables(Database desiredModel, boolean continueOnError) throws DatabaseOperationException
{
Connection connection = borrowConnection();
try
{
- alterTables(connection, desiredDb, continueOnError);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
+
+ alterModel(currentModel, desiredModel, continueOnError);
}
finally
{
@@ -515,13 +675,15 @@
/**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Database desiredDb) throws DatabaseOperationException
+ public void alterTables(Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
{
Connection connection = borrowConnection();
try
{
- return getAlterTablesSql(connection, desiredDb);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
+
+ alterModel(currentModel, desiredModel, params, continueOnError);
}
finally
{
@@ -532,13 +694,15 @@
/**
* {@inheritDoc}
*/
- public void alterTables(Database desiredDb, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
+ public void alterTables(String catalog, String schema, String[] tableTypes, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
{
Connection connection = borrowConnection();
try
{
- alterTables(connection, desiredDb, params, continueOnError);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+
+ alterModel(currentModel, desiredModel, continueOnError);
}
finally
{
@@ -549,13 +713,15 @@
/**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Database desiredDb, CreationParameters params) throws DatabaseOperationException
+ public void alterTables(String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
{
Connection connection = borrowConnection();
try
{
- return getAlterTablesSql(connection, desiredDb, params);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+
+ alterModel(currentModel, desiredModel, params, continueOnError);
}
finally
{
@@ -568,119 +734,99 @@
*/
public void alterTables(Connection connection, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
{
- String sql = getAlterTablesSql(connection, desiredModel);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
- evaluateBatch(connection, sql, continueOnError);
+ alterModel(currentModel, desiredModel, continueOnError);
}
/**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Connection connection, Database desiredModel) throws DatabaseOperationException
+ public void alterTables(Connection connection, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
{
- String sql = null;
Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
- try
- {
- StringWriter buffer = new StringWriter();
-
- getSqlBuilder().setWriter(buffer);
- getSqlBuilder().alterDatabase(currentModel, desiredModel, null);
- sql = buffer.toString();
- }
- catch (IOException ex)
- {
- // won't happen because we're using a string writer
- }
- return sql;
+ alterModel(currentModel, desiredModel, params, continueOnError);
}
/**
* {@inheritDoc}
*/
- public void alterTables(Connection connection, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
+ public void alterTables(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
{
- String sql = getAlterTablesSql(connection, desiredModel, params);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
- evaluateBatch(connection, sql, continueOnError);
+ alterModel(currentModel, desiredModel, continueOnError);
}
/**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Connection connection, Database desiredModel, CreationParameters params) throws DatabaseOperationException
+ public void alterTables(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
{
- String sql = null;
- Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
-
- try
- {
- StringWriter buffer = new StringWriter();
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
- getSqlBuilder().setWriter(buffer);
- getSqlBuilder().alterDatabase(currentModel, desiredModel, params);
- sql = buffer.toString();
- }
- catch (IOException ex)
- {
- // won't happen because we're using a string writer
- }
- return sql;
+ alterModel(currentModel, desiredModel, params, continueOnError);
}
- /**
+ /**
* {@inheritDoc}
*/
- public void alterTables(String catalog, String schema, String[] tableTypes, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
- {
+ public String getAlterTablesSql(Database desiredModel) throws DatabaseOperationException
+ {
Connection connection = borrowConnection();
try
{
- alterTables(connection, catalog, schema, tableTypes, desiredModel, continueOnError);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
+
+ return getAlterModelSql(currentModel, desiredModel);
}
finally
{
returnConnection(connection);
}
- }
+ }
- /**
+ /**
* {@inheritDoc}
*/
- public String getAlterTablesSql(String catalog, String schema, String[] tableTypes, Database desiredModel) throws DatabaseOperationException
- {
+ public String getAlterTablesSql(Database desiredModel, CreationParameters params) throws DatabaseOperationException
+ {
Connection connection = borrowConnection();
try
{
- return getAlterTablesSql(connection, catalog, schema, tableTypes, desiredModel);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
+
+ return getAlterModelSql(currentModel, desiredModel, params);
}
finally
{
returnConnection(connection);
}
- }
+ }
- /**
+ /**
* {@inheritDoc}
*/
- public void alterTables(String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
- {
+ public String getAlterTablesSql(String catalog, String schema, String[] tableTypes, Database desiredModel) throws DatabaseOperationException
+ {
Connection connection = borrowConnection();
try
{
- alterTables(connection, catalog, schema, tableTypes, desiredModel, params, continueOnError);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+
+ return getAlterModelSql(currentModel, desiredModel);
}
finally
{
returnConnection(connection);
}
- }
+ }
- /**
+ /**
* {@inheritDoc}
*/
public String getAlterTablesSql(String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params) throws DatabaseOperationException
@@ -689,38 +835,78 @@
try
{
- return getAlterTablesSql(connection, catalog, schema, tableTypes, desiredModel, params);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+
+ return getAlterModelSql(currentModel, desiredModel, params);
}
finally
{
returnConnection(connection);
}
- }
+ }
- /**
+ /**
* {@inheritDoc}
*/
- public void alterTables(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
+ public String getAlterTablesSql(Connection connection, Database desiredModel) throws DatabaseOperationException
{
- String sql = getAlterTablesSql(connection, catalog, schema, tableTypes, desiredModel);
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
- evaluateBatch(connection, sql, continueOnError);
- }
+ return getAlterModelSql(currentModel, desiredModel);
+ }
- /**
+ /**
+ * {@inheritDoc}
+ */
+ public String getAlterTablesSql(Connection connection, Database desiredModel, CreationParameters params) throws DatabaseOperationException
+ {
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName());
+
+ return getAlterModelSql(currentModel, desiredModel, params);
+ }
+
+ /**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel) throws DatabaseOperationException
- {
- String sql = null;
+ public String getAlterTablesSql(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel) throws DatabaseOperationException
+ {
Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+ return getAlterModelSql(currentModel, desiredModel);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAlterTablesSql(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params) throws DatabaseOperationException
+ {
+ Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+
+ return getAlterModelSql(currentModel, desiredModel, params);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAlterModelSql(Database currentModel, Database desiredModel) throws DatabaseOperationException
+ {
+ return getAlterModelSql(currentModel, desiredModel, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getAlterModelSql(Database currentModel, Database desiredModel, CreationParameters params) throws DatabaseOperationException
+ {
+ List changes = getChanges(currentModel, desiredModel);
+ String sql = null;
+
try
{
StringWriter buffer = new StringWriter();
getSqlBuilder().setWriter(buffer);
- getSqlBuilder().alterDatabase(currentModel, desiredModel, null);
+ processChanges(currentModel, changes, params);
sql = buffer.toString();
}
catch (IOException ex)
@@ -728,40 +914,61 @@
// won't happen because we're using a string writer
}
return sql;
- }
+ }
- /**
+ /**
* {@inheritDoc}
*/
- public void alterTables(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
- {
- String sql = getAlterTablesSql(connection, catalog, schema, tableTypes, desiredModel, params);
+ public void alterModel(Database currentModel, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
+ {
+ Connection connection = borrowConnection();
- evaluateBatch(connection, sql, continueOnError);
- }
+ try
+ {
+ alterModel(connection, currentModel, desiredModel, continueOnError);
+ }
+ finally
+ {
+ returnConnection(connection);
+ }
+ }
- /**
+ /**
* {@inheritDoc}
*/
- public String getAlterTablesSql(Connection connection, String catalog, String schema, String[] tableTypes, Database desiredModel, CreationParameters params) throws DatabaseOperationException
- {
- String sql = null;
- Database currentModel = readModelFromDatabase(connection, desiredModel.getName(), catalog, schema, tableTypes);
+ public void alterModel(Database currentModel, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
+ {
+ Connection connection = borrowConnection();
try
{
- StringWriter buffer = new StringWriter();
-
- getSqlBuilder().setWriter(buffer);
- getSqlBuilder().alterDatabase(currentModel, desiredModel, params);
- sql = buffer.toString();
+ alterModel(connection, currentModel, desiredModel, params, continueOnError);
}
- catch (IOException ex)
+ finally
{
- // won't happen because we're using a string writer
+ returnConnection(connection);
}
- return sql;
- }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void alterModel(Connection connection, Database currentModel, Database desiredModel, boolean continueOnError) throws DatabaseOperationException
+ {
+ String sql = getAlterModelSql(currentModel, desiredModel);
+
+ evaluateBatch(connection, sql, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void alterModel(Connection connection, Database currentModel, Database desiredModel, CreationParameters params, boolean continueOnError) throws DatabaseOperationException
+ {
+ String sql = getAlterModelSql(currentModel, desiredModel, params);
+
+ evaluateBatch(connection, sql, continueOnError);
+ }
/**
* {@inheritDoc}
@@ -817,11 +1024,35 @@
*/
public void dropTables(Database model, boolean continueOnError) throws DatabaseOperationException
{
+ dropModel(model, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dropTables(Connection connection, Database model, boolean continueOnError) throws DatabaseOperationException
+ {
+ dropModel(connection, model, continueOnError);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getDropTablesSql(Database model, boolean continueOnError)
+ {
+ return getDropModelSql(model);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void dropModel(Database model, boolean continueOnError) throws DatabaseOperationException
+ {
Connection connection = borrowConnection();
try
{
- dropTables(connection, model, continueOnError);
+ dropModel(connection, model, continueOnError);
}
finally
{
@@ -832,9 +1063,9 @@
/**
* {@inheritDoc}
*/
- public void dropTables(Connection connection, Database model, boolean continueOnError) throws DatabaseOperationException
+ public void dropModel(Connection connection, Database model, boolean continueOnError) throws DatabaseOperationException
{
- String sql = getDropTablesSql(model, continueOnError);
+ String sql = getDropModelSql(model);
evaluateBatch(connection, sql, continueOnError);
}
@@ -842,7 +1073,7 @@
/**
* {@inheritDoc}
*/
- public String getDropTablesSql(Database model, boolean continueOnError)
+ public String getDropModelSql(Database model)
{
String sql = null;
@@ -862,6 +1093,405 @@
}
/**
+ * Processes the given changes in the specified order. Basically, this method finds the
+ * appropriate handler method (one of the <code>processChange</code> methods) defined in
+ * the concrete sql builder for each change, and invokes it.
+ *
+ * @param model The database model; this object is not going to be changed by this method
+ * @param changes The changes
+ * @param params The parameters used in the creation of new tables. Note that for existing
+ * tables, the parameters won't be applied
+ * @return The changed database model
+ */
+ protected Database processChanges(Database model,
+ Collection changes,
+ CreationParameters params) throws IOException, DdlUtilsException
+ {
+ Database currentModel = new CloneHelper().clone(model);
+
+ for (Iterator it = changes.iterator(); it.hasNext();)
+ {
+ invokeChangeHandler(currentModel, params, (ModelChange)it.next());
+ }
+ return currentModel;
+ }
+
+ /**
+ * Invokes the change handler (one of the <code>processChange</code> methods) for the given
+ * change object.
+ *
+ * @param currentModel The current 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
+ */
+ private void invokeChangeHandler(Database currentModel,
+ CreationParameters params,
+ ModelChange change) throws IOException
+ {
+ Class curClass = getClass();
+
+ // find the handler for the change
+ while ((curClass != null) && !Object.class.equals(curClass))
+ {
+ try
+ {
+ Method method = null;
+
+ try
+ {
+ method = curClass.getDeclaredMethod("processChange",
+ new Class[] { Database.class,
+ CreationParameters.class,
+ change.getClass() });
+ }
+ catch (NoSuchMethodException ex)
+ {
+ // we actually expect this one
+ }
+
+ if (method != null)
+ {
+ method.invoke(this, new Object[] { currentModel, params, change });
+ return;
+ }
+ else
+ {
+ curClass = curClass.getSuperclass();
+ }
+ }
+ catch (InvocationTargetException ex)
+ {
+ if (ex.getTargetException() instanceof IOException)
+ {
+ throw (IOException)ex.getTargetException();
+ }
+ else
+ {
+ throw new DdlUtilsException(ex.getTargetException());
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new DdlUtilsException(ex);
+ }
+ }
+ throw new DdlUtilsException("No handler for change of type " + change.getClass().getName() + " defined");
+ }
+
+ /**
+ * Finds the table changed by the change object in the given model.
+ *
+ * @param currentModel The model to find the table in
+ * @param change The table change
+ * @return The table
+ * @throws ModelException If the table could not be found
+ */
+ protected Table findChangedTable(Database currentModel, TableChange change) throws ModelException
+ {
+ Table table = currentModel.findTable(change.getChangedTable(),
+ getPlatformInfo().isDelimitedIdentifiersSupported());
+
+ if (table == null)
+ {
+ throw new ModelException("Could not find table " + change.getChangedTable() + " in the given model");
+ }
+ else
+ {
+ return table;
+ }
+ }
+
+ /**
+ * Finds the index changed by the change object in the given model.
+ *
+ * @param currentModel The model to find the index in
+ * @param change The index change
+ * @return The index
+ * @throws ModelException If the index could not be found
+ */
+ protected Index findChangedIndex(Database currentModel, IndexChange change) throws ModelException
+ {
+ Index index = change.findChangedIndex(currentModel,
+ getPlatformInfo().isDelimitedIdentifiersSupported());
+
+ if (index == null)
+ {
+ throw new ModelException("Could not find the index to change in table " + change.getChangedTable() + " in the given model");
+ }
+ else
+ {
+ return index;
+ }
+ }
+
+ /**
+ * Finds the foreign key changed by the change object in the given model.
+ *
+ * @param currentModel The model to find the foreign key in
+ * @param change The foreign key change
+ * @return The foreign key
+ * @throws ModelException If the foreign key could not be found
+ */
+ protected ForeignKey findChangedForeignKey(Database currentModel, ForeignKeyChange change) throws ModelException
+ {
+ ForeignKey fk = change.findChangedForeignKey(currentModel,
+ getPlatformInfo().isDelimitedIdentifiersSupported());
+
+ if (fk == null)
+ {
+ throw new ModelException("Could not find the foreign key to change in table " + change.getChangedTable() + " in the given model");
+ }
+ else
+ {
+ return fk;
+ }
+ }
+
+ /**
+ * Processes a change representing the addition of a table.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ AddTableChange change) throws IOException
+ {
+ getSqlBuilder().createTable(currentModel,
+ change.getNewTable(),
+ params == null ? null : params.getParametersFor(change.getNewTable()));
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the removal of a table.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ RemoveTableChange change) throws IOException, ModelException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+
+ getSqlBuilder().dropTable(changedTable);
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the addition of a foreign key.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ AddForeignKeyChange change) throws IOException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+
+ getSqlBuilder().createForeignKey(currentModel,
+ changedTable,
+ change.getNewForeignKey());
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the removal of a foreign key.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ RemoveForeignKeyChange change) throws IOException, ModelException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+ ForeignKey changedFk = findChangedForeignKey(currentModel, change);
+
+ getSqlBuilder().dropForeignKey(changedTable, changedFk);
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the addition of an index.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ AddIndexChange change) throws IOException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+
+ getSqlBuilder().createIndex(changedTable, change.getNewIndex());
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the removal of an index.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ RemoveIndexChange change) throws IOException, ModelException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+ Index changedIndex = findChangedIndex(currentModel, change);
+
+ getSqlBuilder().dropIndex(changedTable, changedIndex);
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the addition of a column.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ AddColumnChange change) throws IOException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+
+ getSqlBuilder().addColumn(changedTable, change.getNewColumn());
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the addition of a primary key.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ AddPrimaryKeyChange change) throws IOException
+ {
+ Table changedTable = findChangedTable(currentModel, change);
+ String[] pkColumnNames = change.getPrimaryKeyColumns();
+ Column[] pkColumns = new Column[pkColumnNames.length];
+
+ for (int colIdx = 0; colIdx < pkColumns.length; colIdx++)
+ {
+ pkColumns[colIdx] = changedTable.findColumn(pkColumnNames[colIdx], isDelimitedIdentifierModeOn());
+ }
+ getSqlBuilder().createPrimaryKey(changedTable, pkColumns);
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * Processes a change representing the recreation of a table.
+ *
+ * @param currentModel The current 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
+ */
+ public void processChange(Database currentModel,
+ CreationParameters params,
+ RecreateTableChange change) throws IOException
+ {
+ // we can only copy the data if no required columns without default value and
+ // non-autoincrement have been added
+ boolean canMigrateData = true;
+
+ for (Iterator it = change.getOriginalChanges().iterator(); canMigrateData && it.hasNext();)
+ {
+ TableChange curChange = (TableChange)it.next();
+
+ if (curChange instanceof AddColumnChange)
+ {
+ AddColumnChange addColumnChange = (AddColumnChange)curChange;
+
+ if (addColumnChange.getNewColumn().isRequired() &&
+ !addColumnChange.getNewColumn().isAutoIncrement() &&
+ (addColumnChange.getNewColumn().getDefaultValue() == null))
+ {
+ _log.warn("Data cannot be retained in table " + change.getChangedTable() +
+ " because of the addition of the required column " + addColumnChange.getNewColumn().getName());
+ canMigrateData = false;
+ }
+ }
+ }
+
+ Table changedTable = findChangedTable(currentModel, change);
+ Table targetTable = change.getTargetTable();
+ Map parameters = (params == null ? null : params.getParametersFor(targetTable));
+
+ if (canMigrateData)
+ {
+ Table tempTable = getTemporaryTableFor(targetTable);
+
+ getSqlBuilder().createTemporaryTable(currentModel, tempTable, parameters);
+ getSqlBuilder().copyData(changedTable, 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
+ getSqlBuilder().dropTable(changedTable);
+ getSqlBuilder().createTable(currentModel, targetTable, parameters);
+ getSqlBuilder().copyData(tempTable, targetTable);
+ getSqlBuilder().dropTemporaryTable(currentModel, tempTable);
+ }
+ else
+ {
+ getSqlBuilder().dropTable(changedTable);
+ getSqlBuilder().createTable(currentModel, targetTable, params.getParametersFor(targetTable));
+ }
+
+ change.apply(currentModel, isDelimitedIdentifierModeOn());
+ }
+
+ /**
+ * 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 targetTable The target table
+ * @return The temporary table
+ */
+ protected Table getTemporaryTableFor(Table targetTable)
+ {
+ CloneHelper cloneHelper = new CloneHelper();
+ Table table = new Table();
+
+ table.setCatalog(targetTable.getCatalog());
+ table.setSchema(targetTable.getSchema());
+ table.setName(targetTable.getName() + "_");
+ table.setType(targetTable.getType());
+ for (int idx = 0; idx < targetTable.getColumnCount(); idx++)
+ {
+ // TODO: clone PK status ?
+ table.addColumn(cloneHelper.clone(targetTable.getColumn(idx), true));
+ }
+
+ return table;
+ }
+
+ /**
* {@inheritDoc}
*/
public Iterator query(Database model, String sql) throws DatabaseOperationException
@@ -1607,7 +2237,8 @@
* @param dynaClass The type
* @param primaryKeys The primary keys
* @param properties The properties to write
- * @param bean Optionally the concrete bean to update
+ * @param oldBean Contains column values to identify the rows to update (i.e. for the WHERE clause)
+ * @param newBean Contains the new column values to write
* @return The SQL required to update the instance
*/
protected String createUpdateSql(Database model, SqlDynaClass dynaClass, SqlDynaProperty[] primaryKeys, SqlDynaProperty[] properties, DynaBean oldBean, DynaBean newBean)