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 [6/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/platform/mssql/MSSqlPlatform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java Mon Dec 10 00:20:47 2007
@@ -19,12 +19,29 @@
  * under the License.
  */
 
+import java.io.IOException;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Types;
+import java.util.Collection;
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.ddlutils.DdlUtilsException;
 import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.ColumnDefinitionChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.PrimaryKeyChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.CreationParameters;
+import org.apache.ddlutils.platform.DefaultTableDefinitionChangesPredicate;
 import org.apache.ddlutils.platform.PlatformImplBase;
 
 /**
@@ -55,6 +72,8 @@
         PlatformInfo info = getPlatformInfo();
 
         info.setMaxIdentifierLength(128);
+        info.setPrimaryKeyColumnAutomaticallyRequired(true);
+        info.setIdentityColumnAutomaticallyRequired(true);
 
         info.addNativeTypeMapping(Types.ARRAY,         "IMAGE",         Types.LONGVARBINARY);
         // BIGINT will be mapped back to BIGINT by the model reader 
@@ -148,5 +167,148 @@
     protected void afterUpdate(Connection connection, Table table) throws SQLException
     {
         afterInsert(connection, table);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected ModelComparator getModelComparator()
+    {
+        return new MSSqlModelComparator(getPlatformInfo(), getTableDefinitionChangesPredicate(), isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+    {
+        return new DefaultTableDefinitionChangesPredicate()
+        {
+            protected boolean isSupported(Table intermediateTable, TableChange change)
+            {
+                if ((change instanceof RemoveColumnChange) ||
+                    (change instanceof AddPrimaryKeyChange) ||
+                    (change instanceof PrimaryKeyChange) ||
+                    (change instanceof RemovePrimaryKeyChange))
+                {
+                    return true;
+                }
+                else if (change instanceof AddColumnChange)
+                {
+                    AddColumnChange addColumnChange = (AddColumnChange)change;
+
+                    // Sql Server can only add not insert columns, and the cannot be requird unless also
+                    // auto increment or with a DEFAULT value
+                    return (addColumnChange.getNextColumn() == null) &&
+                           (!addColumnChange.getNewColumn().isRequired() ||
+                            addColumnChange.getNewColumn().isAutoIncrement() ||
+                            !StringUtils.isEmpty(addColumnChange.getNewColumn().getDefaultValue()));
+                }
+                else if (change instanceof ColumnDefinitionChange)
+                {
+                    ColumnDefinitionChange colDefChange = (ColumnDefinitionChange)change;
+                    Column                 curColumn    = intermediateTable.findColumn(colDefChange.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+                    // Sql Server has no way of adding or removing an IDENTITY constraint
+                    return curColumn.isAutoIncrement() == colDefChange.getNewColumn().isAutoIncrement();
+                }
+                else
+                {
+                    return false;
+                }
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected Database processChanges(Database model, Collection changes, CreationParameters params) throws IOException, DdlUtilsException
+    {
+        if (!changes.isEmpty())
+        {
+            ((MSSqlBuilder)getSqlBuilder()).turnOnQuotation();
+        }
+        return super.processChanges(model, changes, params);
+    }
+
+    /**
+     * Processes the removal of a column from 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,
+                              RemoveColumnChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column removedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((MSSqlBuilder)getSqlBuilder()).dropColumn(changedTable, removedColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the removal of a primary key from 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,
+                              RemovePrimaryKeyChange change) throws IOException
+    {
+        Table changedTable = findChangedTable(currentModel, change);
+
+        ((MSSqlBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the column 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,
+                              ColumnDefinitionChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column changedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((MSSqlBuilder)getSqlBuilder()).recreateColumn(changedTable, changedColumn, change.getNewColumn());
+    }
+    
+    /**
+     * Processes the change of the primary key 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,
+                              PrimaryKeyChange   change) throws IOException
+    {
+        Table    changedTable     = findChangedTable(currentModel, change);
+        String[] newPKColumnNames = change.getNewPrimaryKeyColumns();
+        Column[] newPKColumns     = new Column[newPKColumnNames.length];
+
+        for (int colIdx = 0; colIdx < newPKColumnNames.length; colIdx++)
+        {
+            newPKColumns[colIdx] = changedTable.findColumn(newPKColumnNames[colIdx], isDelimitedIdentifierModeOn());
+        }
+        ((MSSqlBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        getSqlBuilder().createPrimaryKey(changedTable, newPKColumns);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlBuilder.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlBuilder.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlBuilder.java Mon Dec 10 00:20:47 2007
@@ -20,22 +20,11 @@
  */
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
-import org.apache.commons.collections.set.ListOrderedSet;
 import org.apache.ddlutils.Platform;
-import org.apache.ddlutils.alteration.AddColumnChange;
-import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
-import org.apache.ddlutils.alteration.ColumnChange;
-import org.apache.ddlutils.alteration.PrimaryKeyChange;
-import org.apache.ddlutils.alteration.RemoveColumnChange;
-import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
-import org.apache.ddlutils.alteration.TableChange;
 import org.apache.ddlutils.model.Column;
-import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.ForeignKey;
 import org.apache.ddlutils.model.Table;
 import org.apache.ddlutils.platform.SqlBuilder;
@@ -146,13 +135,14 @@
     /**
      * {@inheritDoc}
      */
-    protected void writeExternalForeignKeyDropStmt(Table table, ForeignKey foreignKey) throws IOException
+    public void dropForeignKey(Table table, ForeignKey foreignKey) throws IOException
     {
         writeTableAlterStmt(table);
         print("DROP FOREIGN KEY ");
         printIdentifier(getForeignKeyName(table, foreignKey));
         printEndOfStatement();
 
+        // InnoDB won't drop the auto-index for the foreign key automatically, so we have to do it
         if (foreignKey.isAutoIndexPresent())
         {
             writeTableAlterStmt(table);
@@ -160,192 +150,78 @@
             printIdentifier(getForeignKeyName(table, foreignKey));
             printEndOfStatement();
         }
-    }    
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void processTableStructureChanges(Database currentModel,
-                                                Database desiredModel,
-                                                Table    sourceTable,
-                                                Table    targetTable,
-                                                Map      parameters,
-                                                List     changes) throws IOException
-    {
-        // in order to utilize the ALTER TABLE ADD COLUMN AFTER statement
-        // we have to apply the add column changes in the correct order
-        // thus we first gather all add column changes and then execute them
-        ArrayList addColumnChanges = new ArrayList();
-
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                addColumnChanges.add((AddColumnChange)change);
-                changeIt.remove();
-            }
-        }
-        for (Iterator changeIt = addColumnChanges.iterator(); changeIt.hasNext();)
-        {
-            AddColumnChange addColumnChange = (AddColumnChange)changeIt.next();
-
-            processChange(currentModel, desiredModel, addColumnChange);
-            changeIt.remove();
-        }
-
-        ListOrderedSet changedColumns = new ListOrderedSet();
-        
-        // we don't have to care about the order because the comparator will have ensured
-        // that a add primary key change comes after all necessary columns are present
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof RemoveColumnChange)
-            {
-                processChange(currentModel, desiredModel, (RemoveColumnChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof AddPrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (AddPrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof PrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (PrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof RemovePrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (RemovePrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof ColumnChange)
-            {
-                // we gather all changed columns because we can use the ALTER TABLE MODIFY COLUMN
-                // statement for them
-                changedColumns.add(((ColumnChange)change).getChangedColumn());
-                changeIt.remove();
-            }
-        }
-        for (Iterator columnIt = changedColumns.iterator(); columnIt.hasNext();)
-        {
-            Column sourceColumn = (Column)columnIt.next();
-            Column targetColumn = targetTable.findColumn(sourceColumn.getName(), getPlatform().isDelimitedIdentifierModeOn());
-
-            processColumnChange(sourceTable, targetTable, sourceColumn, targetColumn);
-        }
     }
 
     /**
-     * Processes the addition of a column to a table.
+     * Writes the SQL to add/insert a column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database        currentModel,
-                                 Database        desiredModel,
-                                 AddColumnChange change) throws IOException
+     * @param table      The table
+     * @param newColumn  The new column
+     * @param prevColumn The column after which the new column shall be added; <code>null</code>
+     *                   if the new column is to be inserted at the beginning
+     */
+    public void insertColumn(Table table, Column newColumn, Column prevColumn) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("ADD COLUMN ");
-        writeColumn(change.getChangedTable(), change.getNewColumn());
-        if (change.getPreviousColumn() != null)
+        writeColumn(table, newColumn);
+        if (prevColumn != null)
         {
             print(" AFTER ");
-            printIdentifier(getColumnName(change.getPreviousColumn()));
+            printIdentifier(getColumnName(prevColumn));
         }
         else
         {
             print(" FIRST");
         }
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a column from a table.
+     * Writes the SQL to drop a column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database           currentModel,
-                                 Database           desiredModel,
-                                 RemoveColumnChange change) throws IOException
+     * @param table  The table
+     * @param column The column to drop
+     */
+    public void dropColumn(Table table, Column column) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP COLUMN ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
+        printIdentifier(getColumnName(column));
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a primary key from a table.
+     * Writes the SQL to drop the primary key of the given table.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database               currentModel,
-                                 Database               desiredModel,
-                                 RemovePrimaryKeyChange change) throws IOException
-    {
-        print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
-        printIndent();
-        print("DROP PRIMARY KEY");
-        printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
-    }
-
-    /**
-     * Processes the change of the primary key of a table.
-     * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database         currentModel,
-                                 Database         desiredModel,
-                                 PrimaryKeyChange change) throws IOException
+     * @param table The table
+     */
+    public void dropPrimaryKey(Table table) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP PRIMARY KEY");
         printEndOfStatement();
-        writeExternalPrimaryKeysCreateStmt(change.getChangedTable(), change.getNewPrimaryKeyColumns());
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes a change to a column.
+     * Writes the SQL to recreate a column, e.g. with a different type.  
      * 
-     * @param sourceTable  The current table
-     * @param targetTable  The desired table
-     * @param sourceColumn The current column
-     * @param targetColumn The desired column
-     */
-    protected void processColumnChange(Table  sourceTable,
-                                       Table  targetTable,
-                                       Column sourceColumn,
-                                       Column targetColumn) throws IOException
+     * @param table  The table
+     * @param column The new column definition
+     */
+    public void recreateColumn(Table table, Column column) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(sourceTable));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("MODIFY COLUMN ");
-        writeColumn(targetTable, targetColumn);
+        writeColumn(table, column);
         printEndOfStatement();
     }
 }

Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlModelComparator.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlModelComparator.java?rev=602807&view=auto
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlModelComparator.java (added)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlModelComparator.java Mon Dec 10 00:20:47 2007
@@ -0,0 +1,171 @@
+package org.apache.ddlutils.platform.mysql;
+
+/*
+ * 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 java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddForeignKeyChange;
+import org.apache.ddlutils.alteration.ColumnDefinitionChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.RemoveForeignKeyChange;
+import org.apache.ddlutils.alteration.RemoveIndexChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+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.Reference;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.util.StringUtils;
+
+/**
+ * A model comparator customized for MySql.
+ * 
+ * @version $Revision: $
+ */
+public class MySqlModelComparator extends ModelComparator
+{
+    /**
+     * Creates a new MySql model comparator object.
+     * 
+     * @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 MySqlModelComparator(PlatformInfo                    platformInfo,
+                                TableDefinitionChangesPredicate tableDefChangePredicate,
+                                boolean                         caseSensitive)
+    {
+        super(platformInfo, tableDefChangePredicate, caseSensitive);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected List checkForRemovedIndexes(Database sourceModel,
+                                          Table    sourceTable,
+                                          Database intermediateModel,
+                                          Table    intermediateTable,
+                                          Database targetModel,
+                                          Table    targetTable)
+    {
+        // Handling for http://bugs.mysql.com/bug.php?id=21395: we need to drop and then recreate FKs that reference columns
+        // included in indexes that will be dropped
+        List changes     = super.checkForRemovedIndexes(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable);
+        Set  columnNames = new HashSet();
+
+        for (Iterator it = changes.iterator(); it.hasNext();)
+        {
+            RemoveIndexChange change = (RemoveIndexChange)it.next();
+            Index             index  = change.findChangedIndex(sourceModel, isCaseSensitive());
+
+            for (int colIdx = 0; colIdx < index.getColumnCount(); colIdx++)
+            {
+                columnNames.add(index.getColumn(colIdx).getName());
+            }
+        }
+        if (!columnNames.isEmpty())
+        {
+            // this is only relevant if the columns are referenced by foreign keys in the same table
+            changes.addAll(getForeignKeyRecreationChanges(intermediateTable, targetTable, columnNames));
+        }
+        return changes;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected List compareTables(Database sourceModel,
+                                 Table    sourceTable,
+                                 Database intermediateModel,
+                                 Table    intermediateTable,
+                                 Database targetModel, Table targetTable)
+    {
+        // we need to drop and recreate foreign keys that reference columns whose data type will be changed (but not size)
+        List changes     = super.compareTables(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable);
+        Set  columnNames = new HashSet();
+
+        for (Iterator it = changes.iterator(); it.hasNext();)
+        {
+            Object change = it.next();
+
+            if (change instanceof ColumnDefinitionChange)
+            {
+                ColumnDefinitionChange colDefChange = (ColumnDefinitionChange)change;
+                Column                 sourceColumn = sourceTable.findColumn(colDefChange.getChangedColumn(), isCaseSensitive());
+
+                if (ColumnDefinitionChange.isTypeChanged(getPlatformInfo(), sourceColumn, colDefChange.getNewColumn()))
+                {
+                    columnNames.add(sourceColumn.getName());
+                }
+            }
+        }
+        if (!columnNames.isEmpty())
+        {
+            // we don't need to check for foreign columns as the data type of both local and foreign column need
+            // to be changed, otherwise MySql will complain
+            changes.addAll(getForeignKeyRecreationChanges(intermediateTable, targetTable, columnNames));
+        }
+        return changes;
+    }
+
+    /**
+     * Returns remove and add changes for the foreign keys that reference the indicated columns as a local column.
+     * 
+     * @param intermediateTable The intermediate table
+     * @param targetTable       The target table
+     * @param columnNames       The names of the columns to look for
+     * @return The additional changes
+     */
+    private List getForeignKeyRecreationChanges(Table intermediateTable, Table targetTable, Set columnNames)
+    {
+        List newChanges = new ArrayList();
+
+        for (int fkIdx = 0; fkIdx < targetTable.getForeignKeyCount(); fkIdx++)
+        {
+            ForeignKey targetFk       = targetTable.getForeignKey(fkIdx);
+            ForeignKey intermediateFk = intermediateTable.findForeignKey(targetFk, isCaseSensitive());
+
+            if (intermediateFk != null)
+            {
+                for (int refIdx = 0; refIdx < intermediateFk.getReferenceCount(); refIdx++)
+                {
+                    Reference ref = intermediateFk.getReference(refIdx);
+
+                    for (Iterator colNameIt = columnNames.iterator(); colNameIt.hasNext();)
+                    {
+                        if (StringUtils.equals(ref.getLocalColumnName(), (String)colNameIt.next(), isCaseSensitive()))
+                        {
+                            newChanges.add(new RemoveForeignKeyChange(intermediateTable.getName(), intermediateFk));
+                            newChanges.add(new AddForeignKeyChange(intermediateTable.getName(), intermediateFk));
+                        }
+                    }
+                }
+            }
+        }
+        return newChanges;
+    }
+}
\ No newline at end of file

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlPlatform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlPlatform.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/mysql/MySqlPlatform.java Mon Dec 10 00:20:47 2007
@@ -19,9 +19,24 @@
  * under the License.
  */
 
+import java.io.IOException;
 import java.sql.Types;
 
 import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.ColumnDefinitionChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.PrimaryKeyChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.CreationParameters;
+import org.apache.ddlutils.platform.DefaultTableDefinitionChangesPredicate;
 import org.apache.ddlutils.platform.PlatformImplBase;
 
 /**
@@ -54,6 +69,7 @@
         info.setNonPKIdentityColumnsSupported(false);
         // MySql returns synthetic default values for pk columns
         info.setSyntheticDefaultValueForRequiredReturned(true);
+        info.setPrimaryKeyColumnAutomaticallyRequired(true);
         info.setCommentPrefix("#");
         // Double quotes are only allowed for delimiting identifiers if the server SQL mode includes ANSI_QUOTES 
         info.setDelimiterToken("`");
@@ -97,5 +113,143 @@
     public String getName()
     {
         return DATABASENAME;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected ModelComparator getModelComparator()
+    {
+        return new MySqlModelComparator(getPlatformInfo(), getTableDefinitionChangesPredicate(), isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+    {
+        return new DefaultTableDefinitionChangesPredicate()
+        {
+            protected boolean isSupported(Table intermediateTable, TableChange change)
+            {
+                if (change instanceof AddColumnChange)
+                {
+                    AddColumnChange addColumnChange = (AddColumnChange)change;
+
+                    return !addColumnChange.getNewColumn().isAutoIncrement();
+                }
+                else
+                {
+                    return (change instanceof ColumnDefinitionChange) ||
+                           (change instanceof RemoveColumnChange) ||
+                           (change instanceof AddPrimaryKeyChange) ||
+                           (change instanceof PrimaryKeyChange) ||
+                           (change instanceof RemovePrimaryKeyChange);
+                }
+            }
+        };
+    }
+
+    /**
+     * Processes the addition of a column to 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,
+                              AddColumnChange    change) throws IOException
+    {
+        Table  changedTable = findChangedTable(currentModel, change);
+        Column prevColumn   = null;
+
+        if (change.getPreviousColumn() != null)
+        {
+            prevColumn = changedTable.findColumn(change.getPreviousColumn(), isDelimitedIdentifierModeOn());
+        }
+        ((MySqlBuilder)getSqlBuilder()).insertColumn(changedTable, change.getNewColumn(), prevColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the column 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,
+                              ColumnDefinitionChange change) throws IOException
+    {
+        Table changedTable = findChangedTable(currentModel, change);
+
+        ((MySqlBuilder)getSqlBuilder()).recreateColumn(changedTable, change.getNewColumn());
+    }
+
+    /**
+     * Processes the removal of a column from 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,
+                              RemoveColumnChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column removedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((MySqlBuilder)getSqlBuilder()).dropColumn(changedTable, removedColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the removal of a primary key from 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,
+                              RemovePrimaryKeyChange change) throws IOException
+    {
+        Table changedTable = findChangedTable(currentModel, change);
+
+        ((MySqlBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the primary key 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,
+                              PrimaryKeyChange   change) throws IOException
+    {
+        Table    changedTable     = findChangedTable(currentModel, change);
+        String[] newPKColumnNames = change.getNewPrimaryKeyColumns();
+        Column[] newPKColumns     = new Column[newPKColumnNames.length];
+
+        for (int colIdx = 0; colIdx < newPKColumnNames.length; colIdx++)
+        {
+            newPKColumns[colIdx] = changedTable.findColumn(newPKColumnNames[colIdx], isDelimitedIdentifierModeOn());
+        }
+        
+        ((MySqlBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        getSqlBuilder().createPrimaryKey(changedTable, newPKColumns);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Builder.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Builder.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Builder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Builder.java Mon Dec 10 00:20:47 2007
@@ -21,18 +21,10 @@
 
 import java.io.IOException;
 import java.sql.Types;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.ddlutils.DdlUtilsException;
 import org.apache.ddlutils.Platform;
-import org.apache.ddlutils.alteration.AddColumnChange;
-import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
-import org.apache.ddlutils.alteration.PrimaryKeyChange;
-import org.apache.ddlutils.alteration.RemoveColumnChange;
-import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
-import org.apache.ddlutils.alteration.TableChange;
 import org.apache.ddlutils.model.Column;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.Index;
@@ -246,7 +238,7 @@
     /**
      * {@inheritDoc}
      */
-    public void dropExternalForeignKeys(Table table) throws IOException
+    public void dropForeignKeys(Table table) throws IOException
     {
         // no need to as we drop the table with CASCASE CONSTRAINTS
     }
@@ -254,7 +246,7 @@
     /**
      * {@inheritDoc}
      */
-    public void writeExternalIndexDropStmt(Table table, Index index) throws IOException
+    public void dropIndex(Table table, Index index) throws IOException
     {
         // Index names in Oracle are unique to a schema and hence Oracle does not
         // use the ON <tablename> clause
@@ -365,160 +357,53 @@
     /**
      * {@inheritDoc}
      */
-    protected void processTableStructureChanges(Database currentModel,
-                                                Database desiredModel,
-                                                Table    sourceTable,
-                                                Table    targetTable,
-                                                Map      parameters,
-                                                List     changes) throws IOException
-    {
-        // While Oracle has an ALTER TABLE MODIFY statement, it is somewhat limited
-        // esp. if there is data in the table, so we don't use it
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                AddColumnChange addColumnChange = (AddColumnChange)change;
-
-                // Oracle can only add not insert columns
-                // Also, we cannot add NOT NULL columns unless they have a default value
-                if (!addColumnChange.isAtEnd() ||
-                    (addColumnChange.getNewColumn().isRequired() && (addColumnChange.getNewColumn().getDefaultValue() == null)))
-                {
-                    // we need to rebuild the full table
-                    return;
-                }
-            }
-        }
-
-        // First we drop primary keys as necessary
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof RemovePrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (RemovePrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof PrimaryKeyChange)
-            {
-                PrimaryKeyChange       pkChange       = (PrimaryKeyChange)change;
-                RemovePrimaryKeyChange removePkChange = new RemovePrimaryKeyChange(pkChange.getChangedTable(),
-                                                                                   pkChange.getOldPrimaryKeyColumns());
-
-                processChange(currentModel, desiredModel, removePkChange);
-            }
-        }
-
-        // Next we add/remove columns
-        // While Oracle has an ALTER TABLE MODIFY statement, it is somewhat limited
-        // esp. if there is data in the table, so we don't use it
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                processChange(currentModel, desiredModel, (AddColumnChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof RemoveColumnChange)
-            {
-                processChange(currentModel, desiredModel, (RemoveColumnChange)change);
-                changeIt.remove();
-            }
-        }
-        // Finally we add primary keys
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddPrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (AddPrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof PrimaryKeyChange)
-            {
-                PrimaryKeyChange    pkChange    = (PrimaryKeyChange)change;
-                AddPrimaryKeyChange addPkChange = new AddPrimaryKeyChange(pkChange.getChangedTable(),
-                                                                          pkChange.getNewPrimaryKeyColumns());
-
-                processChange(currentModel, desiredModel, addPkChange);
-                changeIt.remove();
-            }
-        }
-    }
-
-    /**
-     * Processes the addition of a column to a table.
-     * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database        currentModel,
-                                 Database        desiredModel,
-                                 AddColumnChange change) throws IOException
+    public void addColumn(Table table, Column newColumn) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("ADD ");
-        writeColumn(change.getChangedTable(), change.getNewColumn());
+        writeColumn(table, newColumn);
         printEndOfStatement();
-        if (change.getNewColumn().isAutoIncrement())
+        if (newColumn.isAutoIncrement())
         {
-            createAutoIncrementSequence(change.getChangedTable(), change.getNewColumn());
-            createAutoIncrementTrigger(change.getChangedTable(), change.getNewColumn());
+            createAutoIncrementSequence(table, newColumn);
+            createAutoIncrementTrigger(table, newColumn);
         }
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a column from a table.
+     * Writes the SQL to drop a column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database           currentModel,
-                                 Database           desiredModel,
-                                 RemoveColumnChange change) throws IOException
+     * @param table  The table
+     * @param column The column to drop
+     */
+    public void dropColumn(Table table, Column column) throws IOException
     {
-        if (change.getChangedColumn().isAutoIncrement())
+        if (column.isAutoIncrement())
         {
-            dropAutoIncrementTrigger(change.getChangedTable(), change.getChangedColumn());
-            dropAutoIncrementSequence(change.getChangedTable(), change.getChangedColumn());
+            dropAutoIncrementTrigger(table, column);
+            dropAutoIncrementSequence(table, column);
         }
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP COLUMN ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
+        printIdentifier(getColumnName(column));
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a primary key from a table.
+     * Writes the SQL to drop the primary key of the given table.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database               currentModel,
-                                 Database               desiredModel,
-                                 RemovePrimaryKeyChange change) throws IOException
+     * @param table The table
+     */
+    public void dropPrimaryKey(Table table) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP PRIMARY KEY");
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java Mon Dec 10 00:20:47 2007
@@ -19,9 +19,23 @@
  * under the License.
  */
 
+import java.io.IOException;
 import java.sql.Types;
+import java.util.Map;
 
 import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.PrimaryKeyChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.CreationParameters;
+import org.apache.ddlutils.platform.DefaultTableDefinitionChangesPredicate;
 import org.apache.ddlutils.platform.PlatformImplBase;
 
 /**
@@ -56,6 +70,7 @@
 
         info.setMaxIdentifierLength(30);
         info.setIdentityStatusReadingSupported(false);
+        info.setPrimaryKeyColumnAutomaticallyRequired(true);
 
         // Note that the back-mappings are partially done by the model reader, not the driver
         info.addNativeTypeMapping(Types.ARRAY,         "BLOB",             Types.BLOB);
@@ -100,5 +115,109 @@
     public String getName()
     {
         return DATABASENAME;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+    {
+        // While Oracle has an ALTER TABLE MODIFY statement, it is somewhat limited
+        // esp. if there is data in the table, so we don't use it
+        return new DefaultTableDefinitionChangesPredicate()
+        {
+            protected boolean isSupported(Table intermediateTable, TableChange change)
+            {
+                if ((change instanceof AddPrimaryKeyChange) ||
+                    (change instanceof RemovePrimaryKeyChange))
+                {
+                    return true;
+                }
+                else if (change instanceof RemoveColumnChange)
+                {
+                    // TODO: for now we trigger recreating the table, but ideally we should simply add the necessary pk changes
+                    RemoveColumnChange removeColumnChange = (RemoveColumnChange)change;
+                    Column             column             = intermediateTable.findColumn(removeColumnChange.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+                    return !column.isPrimaryKey();
+                }
+                else if (change instanceof AddColumnChange)
+                {
+                    AddColumnChange addColumnChange = (AddColumnChange)change;
+
+                    // Oracle can only add not insert columns
+                    // Also, we cannot add NOT NULL columns unless they have a default value
+                    return addColumnChange.isAtEnd() &&
+                           (!addColumnChange.getNewColumn().isRequired() || (addColumnChange.getNewColumn().getDefaultValue() != null));
+                }
+                else
+                {
+                    return false;
+                }
+            }
+        };
+    }
+
+    /**
+     * Processes the removal of a column from 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,
+                              RemoveColumnChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column removedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((Oracle8Builder)getSqlBuilder()).dropColumn(changedTable, removedColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the removal of a primary key from 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,
+                              RemovePrimaryKeyChange change) throws IOException
+    {
+        Table changedTable = findChangedTable(currentModel, change);
+
+        ((Oracle8Builder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the primary key 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,
+                              PrimaryKeyChange   change) throws IOException
+    {
+        Table    changedTable     = findChangedTable(currentModel, change);
+        String[] newPKColumnNames = change.getNewPrimaryKeyColumns();
+        Column[] newPKColumns     = new Column[newPKColumnNames.length];
+
+        for (int colIdx = 0; colIdx < newPKColumnNames.length; colIdx++)
+        {
+            newPKColumns[colIdx] = changedTable.findColumn(newPKColumnNames[colIdx], isDelimitedIdentifierModeOn());
+        }
+        
+        ((Oracle8Builder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        getSqlBuilder().createPrimaryKey(changedTable, newPKColumns);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java Mon Dec 10 00:20:47 2007
@@ -20,14 +20,9 @@
  */
 
 import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.ddlutils.Platform;
-import org.apache.ddlutils.alteration.AddColumnChange;
-import org.apache.ddlutils.alteration.RemoveColumnChange;
-import org.apache.ddlutils.alteration.TableChange;
 import org.apache.ddlutils.model.Column;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.Index;
@@ -81,7 +76,7 @@
     /**
      * {@inheritDoc}
      */
-    public void writeExternalIndexDropStmt(Table table, Index index) throws IOException
+    public void dropIndex(Table table, Index index) throws IOException
     {
         print("DROP INDEX ");
         printIdentifier(getIndexName(index));
@@ -173,89 +168,22 @@
     }
 
     /**
-     * {@inheritDoc}
-     */
-    protected void processTableStructureChanges(Database currentModel,
-                                                Database desiredModel,
-                                                Table    sourceTable,
-                                                Table    targetTable,
-                                                Map      parameters,
-                                                List     changes) throws IOException
-    {
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                AddColumnChange addColumnChange = (AddColumnChange)change;
-
-                // We can only use PostgreSQL-specific SQL if
-                // * the column is not set to NOT NULL (the constraint would be applied immediately
-                //   which will not work if there is already data in the table)
-                // * the column has no default value (it would be applied after the change which
-                //   means that PostgreSQL would behave differently from other databases where the
-                //   default is applied to every column)
-                // * the column is added at the end of the table (PostgreSQL does not support
-                //   insertion of a column)
-                if (!addColumnChange.getNewColumn().isRequired() &&
-                    (addColumnChange.getNewColumn().getDefaultValue() == null) &&
-                    (addColumnChange.getNextColumn() == null))
-                {
-                    processChange(currentModel, desiredModel, addColumnChange);
-                    changeIt.remove();
-                }
-            }
-            else if (change instanceof RemoveColumnChange)
-            {
-                processChange(currentModel, desiredModel, (RemoveColumnChange)change);
-                changeIt.remove();
-            }
-        }
-        super.processTableStructureChanges(currentModel, desiredModel, sourceTable, targetTable, parameters, changes);
-    }
-
-    /**
-     * Processes the addition of a column to a table.
+     * Writes the SQL to drop a column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database        currentModel,
-                                 Database        desiredModel,
-                                 AddColumnChange change) throws IOException
-    {
-        print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
-        printIndent();
-        print("ADD COLUMN ");
-        writeColumn(change.getChangedTable(), change.getNewColumn());
-        printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
-    }
-
-    /**
-     * Processes the removal of a column from a table.
-     * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database           currentModel,
-                                 Database           desiredModel,
-                                 RemoveColumnChange change) throws IOException
+     * @param table  The table
+     * @param column The column to drop
+     */
+    public void dropColumn(Table table, Column column) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP COLUMN ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
+        printIdentifier(getColumnName(column));
         printEndOfStatement();
-        if (change.getChangedColumn().isAutoIncrement())
+        if (column.isAutoIncrement())
         {
-            dropAutoIncrementSequence(change.getChangedTable(), change.getChangedColumn());
+            dropAutoIncrementSequence(table, column);
         }
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlPlatform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlPlatform.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlPlatform.java Mon Dec 10 00:20:47 2007
@@ -19,6 +19,7 @@
  * under the License.
  */
 
+import java.io.IOException;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.PreparedStatement;
@@ -31,7 +32,16 @@
 import org.apache.commons.beanutils.DynaBean;
 import org.apache.ddlutils.DatabaseOperationException;
 import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
 import org.apache.ddlutils.dynabean.SqlDynaProperty;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.CreationParameters;
+import org.apache.ddlutils.platform.DefaultTableDefinitionChangesPredicate;
 import org.apache.ddlutils.platform.PlatformImplBase;
 
 /**
@@ -239,5 +249,62 @@
         {
             super.setObject(statement, sqlIndex, dynaBean, property);
         }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+    {
+        return new DefaultTableDefinitionChangesPredicate()
+        {
+            protected boolean isSupported(Table intermediateTable, TableChange change)
+            {
+                if (change instanceof RemoveColumnChange)
+                {
+                    return true;
+                }
+                else if (change instanceof AddColumnChange)
+                {
+                    AddColumnChange addColumnChange = (AddColumnChange)change;
+
+                    // We can only handle this if
+                    // * the column is not set to NOT NULL (the constraint would be applied immediately
+                    //   which will not work if there is already data in the table)
+                    // * the column has no default value (it would be applied after the change which
+                    //   means that PostgreSQL would behave differently from other databases where the
+                    //   default is applied to every column)
+                    // * the column is added at the end of the table (PostgreSQL does not support
+                    //   insertion of a column)
+                    return !addColumnChange.getNewColumn().isRequired() &&
+                           (addColumnChange.getNewColumn().getDefaultValue() == null) &&
+                           (addColumnChange.getNextColumn() == null);
+                }
+                else
+                {
+                    // TODO: PK changes ?
+                    return false;
+                }
+            }
+        };
+    }
+
+    /**
+     * Processes the removal of a column from 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,
+                              RemoveColumnChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column removedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((PostgreSqlBuilder)getSqlBuilder()).dropColumn(changedTable, removedColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbBuilder.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbBuilder.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbBuilder.java Mon Dec 10 00:20:47 2007
@@ -20,19 +20,8 @@
  */
 
 import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
 
 import org.apache.ddlutils.Platform;
-import org.apache.ddlutils.alteration.AddColumnChange;
-import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
-import org.apache.ddlutils.alteration.ColumnDefaultValueChange;
-import org.apache.ddlutils.alteration.ColumnRequiredChange;
-import org.apache.ddlutils.alteration.PrimaryKeyChange;
-import org.apache.ddlutils.alteration.RemoveColumnChange;
-import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
-import org.apache.ddlutils.alteration.TableChange;
 import org.apache.ddlutils.model.Column;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.model.ForeignKey;
@@ -79,7 +68,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void writeExternalPrimaryKeysCreateStmt(Table table, Column[] primaryKeyColumns) throws IOException
+    public void createPrimaryKey(Table table, Column[] primaryKeyColumns) throws IOException
     {
         // Note that SapDB does not support the addition of named primary keys
         if ((primaryKeyColumns.length > 0) && shouldGeneratePrimaryKeys(primaryKeyColumns))
@@ -96,24 +85,24 @@
     /**
      * {@inheritDoc}
      */
-    protected void writeExternalForeignKeyCreateStmt(Database database, Table table, ForeignKey key) throws IOException
+    public void createForeignKey(Database database, Table table, ForeignKey foreignKey) throws IOException
     {
-        if (key.getForeignTableName() == null)
+        if (foreignKey.getForeignTableName() == null)
         {
-            _log.warn("Foreign key table is null for key " + key);
+            _log.warn("Foreign key table is null for key " + foreignKey);
         }
         else
         {
             writeTableAlterStmt(table);
 
             print(" ADD FOREIGN KEY ");
-            printIdentifier(getForeignKeyName(table, key));
+            printIdentifier(getForeignKeyName(table, foreignKey));
             print(" (");
-            writeLocalReferences(key);
+            writeLocalReferences(foreignKey);
             print(") REFERENCES ");
-            printIdentifier(getTableName(database.findTable(key.getForeignTableName())));
+            printIdentifier(getTableName(database.findTable(foreignKey.getForeignTableName())));
             print(" (");
-            writeForeignReferences(key);
+            writeForeignReferences(foreignKey);
             print(")");
             printEndOfStatement();
         }
@@ -122,7 +111,7 @@
     /**
      * {@inheritDoc}
      */
-    protected void writeExternalForeignKeyDropStmt(Table table, ForeignKey foreignKey) throws IOException
+    public void dropForeignKey(Table table, ForeignKey foreignKey) throws IOException
     {
         writeTableAlterStmt(table);
         print("DROP FOREIGN KEY ");
@@ -146,208 +135,90 @@
     /**
      * {@inheritDoc}
      */
-    protected void processTableStructureChanges(Database currentModel,
-                                                Database desiredModel,
-                                                Table    sourceTable,
-                                                Table    targetTable,
-                                                Map      parameters,
-                                                List     changes) throws IOException
-    {
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                AddColumnChange addColumnChange = (AddColumnChange)change;
-
-                // SapDB can only add not insert columns
-                if (!addColumnChange.isAtEnd())
-                {
-                    return;
-                }
-            }
-        }
-
-        // First we drop primary keys as necessary
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof RemovePrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (RemovePrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof PrimaryKeyChange)
-            {
-                PrimaryKeyChange       pkChange       = (PrimaryKeyChange)change;
-                RemovePrimaryKeyChange removePkChange = new RemovePrimaryKeyChange(pkChange.getChangedTable(),
-                                                                                   pkChange.getOldPrimaryKeyColumns());
-
-                processChange(currentModel, desiredModel, removePkChange);
-            }
-        }
-        // Next we add/change/remove columns
-        // SapDB has a ALTER TABLE MODIFY COLUMN but it is limited regarding the type conversions
-        // it can perform, so we don't use it here but rather rebuild the table
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddColumnChange)
-            {
-                processChange(currentModel, desiredModel, (AddColumnChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof ColumnDefaultValueChange)
-            {
-                processChange(currentModel, desiredModel, (ColumnDefaultValueChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof ColumnRequiredChange)
-            {
-                processChange(currentModel, desiredModel, (ColumnRequiredChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof RemoveColumnChange)
-            {
-                processChange(currentModel, desiredModel, (RemoveColumnChange)change);
-                changeIt.remove();
-            }
-        }
-        // Finally we add primary keys
-        for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
-        {
-            TableChange change = (TableChange)changeIt.next();
-
-            if (change instanceof AddPrimaryKeyChange)
-            {
-                processChange(currentModel, desiredModel, (AddPrimaryKeyChange)change);
-                changeIt.remove();
-            }
-            else if (change instanceof PrimaryKeyChange)
-            {
-                PrimaryKeyChange    pkChange    = (PrimaryKeyChange)change;
-                AddPrimaryKeyChange addPkChange = new AddPrimaryKeyChange(pkChange.getChangedTable(),
-                                                                          pkChange.getNewPrimaryKeyColumns());
-
-                processChange(currentModel, desiredModel, addPkChange);
-                changeIt.remove();
-            }
-        }
-    }
-
-    /**
-     * Processes the addition of a column to a table.
-     * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database        currentModel,
-                                 Database        desiredModel,
-                                 AddColumnChange change) throws IOException
+    public void addColumn(Table table, Column newColumn) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("ADD ");
-        writeColumn(change.getChangedTable(), change.getNewColumn());
+        writeColumn(table, newColumn);
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a column from a table.
+     * Writes the SQL to drop a column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database           currentModel,
-                                 Database           desiredModel,
-                                 RemoveColumnChange change) throws IOException
+     * @param table  The table
+     * @param column The column to drop
+     */
+    public void dropColumn(Table table, Column column) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
+        printIdentifier(getColumnName(column));
         print(" RELEASE SPACE");
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the removal of a primary key from a table.
+     * Writes the SQL to drop the primary key of the given table.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database               currentModel,
-                                 Database               desiredModel,
-                                 RemovePrimaryKeyChange change) throws IOException
+     * @param table The table
+     */
+    public void dropPrimaryKey(Table table) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("DROP PRIMARY KEY");
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the change of the required constraint of a column.
+     * Writes the SQL to set the required status of the given column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database             currentModel,
-                                 Database             desiredModel,
-                                 ColumnRequiredChange change) throws IOException
+     * @param table      The table
+     * @param column     The column to change
+     * @param isRequired Whether the column shall be required
+     */
+    public void changeColumnRequiredStatus(Table table, Column column, boolean isRequired) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("COLUMN ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
-        if (change.getChangedColumn().isRequired())
+        printIdentifier(getColumnName(column));
+        if (isRequired)
         {
-            print(" DEFAULT NULL");
+            print(" NOT NULL");
         }
         else
         {
-            print(" NOT NULL");
+            print(" DEFAULT NULL");
         }
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 
     /**
-     * Processes the change of the default value of a column.
+     * Writes the SQL to set the default value of the given column.
      * 
-     * @param currentModel The current database schema
-     * @param desiredModel The desired database schema
-     * @param change       The change object
-     */
-    protected void processChange(Database                 currentModel,
-                                 Database                 desiredModel,
-                                 ColumnDefaultValueChange change) throws IOException
+     * @param table           The table
+     * @param column          The column to change
+     * @param newDefaultValue The new default value
+     */
+    public void changeColumnDefaultValue(Table table, Column column, String newDefaultValue) throws IOException
     {
         print("ALTER TABLE ");
-        printlnIdentifier(getTableName(change.getChangedTable()));
+        printlnIdentifier(getTableName(table));
         printIndent();
         print("COLUMN ");
-        printIdentifier(getColumnName(change.getChangedColumn()));
+        printIdentifier(getColumnName(column));
 
-        Table   curTable   = currentModel.findTable(change.getChangedTable().getName(), getPlatform().isDelimitedIdentifierModeOn());
-        Column  curColumn  = curTable.findColumn(change.getChangedColumn().getName(), getPlatform().isDelimitedIdentifierModeOn());
-        boolean hasDefault = curColumn.getParsedDefaultValue() != null;
+        boolean hasDefault = column.getParsedDefaultValue() != null;
 
-        if (isValidDefaultValue(change.getNewDefaultValue(), curColumn.getTypeCode()))
+        if (isValidDefaultValue(newDefaultValue, column.getTypeCode()))
         {
             if (hasDefault)
             {
@@ -357,13 +228,12 @@
             {
                 print(" ADD DEFAULT ");
             }
-            printDefaultValue(change.getNewDefaultValue(), curColumn.getTypeCode());
+            printDefaultValue(newDefaultValue, column.getTypeCode());
         }
         else if (hasDefault)
         {
             print(" DROP DEFAULT");
         }
         printEndOfStatement();
-        change.apply(currentModel, getPlatform().isDelimitedIdentifierModeOn());
     }
 }

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java?rev=602807&r1=602806&r2=602807&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java Mon Dec 10 00:20:47 2007
@@ -19,10 +19,26 @@
  * under the License.
  */
 
+import java.io.IOException;
 import java.sql.Types;
 
 import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.AddPrimaryKeyChange;
+import org.apache.ddlutils.alteration.ColumnDefinitionChange;
+import org.apache.ddlutils.alteration.ModelComparator;
+import org.apache.ddlutils.alteration.PrimaryKeyChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.alteration.TableDefinitionChangesPredicate;
+import org.apache.ddlutils.model.Column;
+import org.apache.ddlutils.model.Database;
+import org.apache.ddlutils.model.Table;
+import org.apache.ddlutils.platform.CreationParameters;
+import org.apache.ddlutils.platform.DefaultTableDefinitionChangesPredicate;
 import org.apache.ddlutils.platform.PlatformImplBase;
+import org.apache.ddlutils.util.StringUtils;
 
 /**
  * The SapDB platform implementation.
@@ -46,6 +62,7 @@
         PlatformInfo info = getPlatformInfo();
 
         info.setMaxIdentifierLength(32);
+        info.setPrimaryKeyColumnAutomaticallyRequired(true);
         info.setCommentPrefix("/*");
         info.setCommentSuffix("*/");
 
@@ -92,5 +109,160 @@
     public String getName()
     {
         return DATABASENAME;
+    }
+
+    /**
+     * Returns the model comparator for this platform.
+     * 
+     * @return The comparator
+     */
+    protected ModelComparator getModelComparator()
+    {
+        ModelComparator comparator = super.getModelComparator();
+
+        comparator.setCanDropPrimaryKeyColumns(false);
+        comparator.setGeneratePrimaryKeyChanges(false);
+        return comparator;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected TableDefinitionChangesPredicate getTableDefinitionChangesPredicate()
+    {
+        return new DefaultTableDefinitionChangesPredicate()
+        {
+            protected boolean isSupported(Table intermediateTable, TableChange change)
+            {
+                if ((change instanceof RemoveColumnChange) ||
+                    (change instanceof AddPrimaryKeyChange) ||
+                    (change instanceof PrimaryKeyChange) ||
+                    (change instanceof RemovePrimaryKeyChange))
+                {
+                    return true;
+                }
+                else if (change instanceof AddColumnChange) 
+                {
+                    AddColumnChange addColumnChange = (AddColumnChange)change;
+
+                    // SapDB can only add not insert columns, and required columns have to have
+                    // a default value or be IDENTITY
+                    return (addColumnChange.getNextColumn() == null) &&
+                           (!addColumnChange.getNewColumn().isRequired() ||
+                            !StringUtils.isEmpty(addColumnChange.getNewColumn().getDefaultValue()));
+                }
+                else if (change instanceof ColumnDefinitionChange)
+                {
+                    ColumnDefinitionChange colChange = (ColumnDefinitionChange)change;
+
+                    // SapDB has a ALTER TABLE MODIFY COLUMN but it is limited regarding the type conversions
+                    // it can perform, so we don't use it here but rather rebuild the table
+                    Column curColumn = intermediateTable.findColumn(colChange.getChangedColumn(), isDelimitedIdentifierModeOn());
+                    Column newColumn = colChange.getNewColumn();
+
+                    // we can however handle the change if only the default value or the required status was changed
+                    return ((curColumn.getTypeCode() == newColumn.getTypeCode()) &&
+                           (!getPlatformInfo().hasSize(curColumn.getTypeCode()) || StringUtils.equals(curColumn.getSize(), newColumn.getSize())) &&
+                           (curColumn.isAutoIncrement() == newColumn.isAutoIncrement()));
+                }
+                else
+                {
+                    return false;
+                }
+            }
+        };
+    }
+
+    /**
+     * Processes the removal of a column from 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,
+                              RemoveColumnChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column removedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        ((SapDbBuilder)getSqlBuilder()).dropColumn(changedTable, removedColumn);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the removal of a primary key from 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,
+                              RemovePrimaryKeyChange change) throws IOException
+    {
+        Table changedTable = findChangedTable(currentModel, change);
+
+        ((SapDbBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the primary key 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,
+                              PrimaryKeyChange   change) throws IOException
+    {
+        Table    changedTable     = findChangedTable(currentModel, change);
+        String[] newPKColumnNames = change.getNewPrimaryKeyColumns();
+        Column[] newPKColumns     = new Column[newPKColumnNames.length];
+
+        for (int colIdx = 0; colIdx < newPKColumnNames.length; colIdx++)
+        {
+            newPKColumns[colIdx] = changedTable.findColumn(newPKColumnNames[colIdx], isDelimitedIdentifierModeOn());
+        }
+        
+        ((SapDbBuilder)getSqlBuilder()).dropPrimaryKey(changedTable);
+        getSqlBuilder().createPrimaryKey(changedTable, newPKColumns);
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
+    }
+
+    /**
+     * Processes the change of the column 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,
+                              ColumnDefinitionChange change) throws IOException
+    {
+        Table  changedTable  = findChangedTable(currentModel, change);
+        Column changedColumn = changedTable.findColumn(change.getChangedColumn(), isDelimitedIdentifierModeOn());
+
+        if (!StringUtils.equals(changedColumn.getDefaultValue(), change.getNewColumn().getDefaultValue()))
+        {
+            ((SapDbBuilder)getSqlBuilder()).changeColumnDefaultValue(changedTable,
+                                                                  changedColumn,
+                                                                  change.getNewColumn().getDefaultValue());
+        }
+        if (changedColumn.isRequired() != change.getNewColumn().isRequired())
+        {
+            ((SapDbBuilder)getSqlBuilder()).changeColumnRequiredStatus(changedTable,
+                                                                    changedColumn,
+                                                                    change.getNewColumn().isRequired());
+        }
+        change.apply(currentModel, isDelimitedIdentifierModeOn());
     }
 }