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 2006/03/02 23:46:17 UTC

svn commit: r382539 - in /db/ddlutils/trunk/src/java/org/apache/ddlutils: model/ForeignKey.java model/Reference.java model/Table.java platform/SqlBuilder.java

Author: tomdz
Date: Thu Mar  2 14:46:16 2006
New Revision: 382539

URL: http://svn.apache.org/viewcvs?rev=382539&view=rev
Log:
Enhanced foreign key change detection when altering tables

Modified:
    db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/ForeignKey.java?rev=382539&r1=382538&r2=382539&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 Thu Mar  2 14:46:16 2006
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import java.util.HashSet;
 import java.util.Iterator;
 
 import org.apache.commons.collections.set.ListOrderedSet;
@@ -247,6 +248,48 @@
                                       .append(_foreignTableName, other._foreignTableName)
                                       .append(_references,       other._references)
                                       .isEquals();
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Compares this foreign key to the given one while ignoring the case of identifiers.
+     * 
+     * @param otherFk The other foreign key
+     */
+    public boolean equalsIgnoreCase(ForeignKey otherFk)
+    {
+        if (_name.equalsIgnoreCase(otherFk._name) &&
+            _foreignTableName.equalsIgnoreCase(otherFk._foreignTableName))
+        {
+            HashSet otherRefs = new HashSet();
+    
+            otherRefs.addAll(otherFk._references);
+            for (Iterator it = _references.iterator(); it.hasNext();)
+            {
+                Reference curLocalRef = (Reference)it.next();
+                boolean   found       = false;
+
+                for (Iterator otherIt = otherRefs.iterator(); otherIt.hasNext();)
+                {
+                    Reference curOtherRef = (Reference)otherIt.next();
+
+                    if (curLocalRef.equalsIgnoreCase(curOtherRef))
+                    {
+                        otherIt.remove();
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found)
+                {
+                    return false;
+                }
+            }
+            return otherRefs.isEmpty();
         }
         else
         {

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Reference.java?rev=382539&r1=382538&r2=382539&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 Thu Mar  2 14:46:16 2006
@@ -208,6 +208,18 @@
     }
 
     /**
+     * Compares this reference to the given one while ignoring the case of identifiers.
+     * 
+     * @param otherRef The other reference
+     */
+    public boolean equalsIgnoreCase(Reference otherRef)
+    {
+        return (otherRef != null) &&
+               _localColumnName.equalsIgnoreCase(otherRef._localColumnName) &&
+               _foreignColumnName.equalsIgnoreCase(otherRef._foreignColumnName);
+    }
+
+    /**
      * {@inheritDoc}
      */
     public int hashCode()

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java?rev=382539&r1=382538&r2=382539&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 Thu Mar  2 14:46:16 2006
@@ -604,6 +604,28 @@
     }
 
     /**
+     * Finds the foreign key in this table that is equal to the supplied foreign key.
+     * 
+     * @param key           The foreign key to search for
+     * @param caseSensitive Whether case matters for the names
+     * @return The found foreign key
+     */
+    public ForeignKey findForeignKey(ForeignKey key, boolean caseSensitive)
+    {
+        for (int idx = 0; idx < getForeignKeyCount(); idx++)
+        {
+            ForeignKey fk = getForeignKey(idx);
+
+            if ((caseSensitive  && fk.equals(key)) ||
+                (!caseSensitive && fk.equalsIgnoreCase(key)))
+            {
+                return fk;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns the primary key columns of this table.
      * 
      * @return The primary key columns

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java?rev=382539&r1=382538&r2=382539&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java Thu Mar  2 14:46:16 2006
@@ -26,6 +26,7 @@
 import java.util.Locale;
 import java.util.Map;
 
+import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.map.ListOrderedMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
@@ -37,6 +38,7 @@
 import org.apache.ddlutils.model.ForeignKey;
 import org.apache.ddlutils.model.Index;
 import org.apache.ddlutils.model.IndexColumn;
+import org.apache.ddlutils.model.Reference;
 import org.apache.ddlutils.model.Table;
 import org.apache.ddlutils.model.TypeMap;
 
@@ -429,7 +431,7 @@
         for (int columnIdx = 0; columnIdx < desiredTable.getColumnCount(); columnIdx++)
         {
             Column desiredColumn = desiredTable.getColumn(columnIdx);
-            Column currentColumn = currentTable.findColumn(desiredColumn.getName());
+            Column currentColumn = currentTable.findColumn(desiredColumn.getName(), getPlatformInfo().isUseDelimitedIdentifiers());
 
             if (null == currentColumn)
             {
@@ -468,7 +470,7 @@
         for (int fkIdx = 0; fkIdx < desiredTable.getForeignKeyCount(); fkIdx++)
         {
             ForeignKey desiredFk = desiredTable.getForeignKey(fkIdx);
-            ForeignKey currentFk = currentTable.findForeignKey(desiredFk);
+            ForeignKey currentFk = findCorrespondingForeignKey(currentTable, desiredFk);
 
             if (currentFk == null)
             {
@@ -485,7 +487,7 @@
         for (int indexIdx = 0; indexIdx < desiredTable.getIndexCount(); indexIdx++)
         {
             Index desiredIndex = desiredTable.getIndex(indexIdx);
-            Index currentIndex = currentTable.findIndex(desiredIndex.getName());
+            Index currentIndex = currentTable.findIndex(desiredIndex.getName(), getPlatformInfo().isUseDelimitedIdentifiers());
 
             if (currentIndex == null)
             {
@@ -501,7 +503,7 @@
         for (int fkIdx = 0; fkIdx < currentTable.getForeignKeyCount(); fkIdx++)
         {
             ForeignKey currentFk = currentTable.getForeignKey(fkIdx);
-            ForeignKey desiredFk = desiredTable.findForeignKey(currentFk);
+            ForeignKey desiredFk = findCorrespondingForeignKey(desiredTable, currentFk);
 
             if (desiredFk == null)
             {
@@ -521,7 +523,7 @@
         for (int columnIdx = 0; columnIdx < currentTable.getColumnCount(); columnIdx++)
         {
             Column currentColumn = currentTable.getColumn(columnIdx);
-            Column desiredColumn = desiredTable.findColumn(currentColumn.getName());
+            Column desiredColumn = desiredTable.findColumn(currentColumn.getName(), getPlatformInfo().isUseDelimitedIdentifiers());
 
             if (desiredColumn == null)
             {
@@ -550,7 +552,7 @@
         for (int indexIdx = 0; indexIdx < currentTable.getIndexCount(); indexIdx++)
         {
             Index currentIndex = currentTable.getIndex(indexIdx);
-            Index desiredIndex = desiredTable.findIndex(currentIndex.getName());
+            Index desiredIndex = desiredTable.findIndex(currentIndex.getName(), getPlatformInfo().isUseDelimitedIdentifiers());
 
             if (desiredIndex == null)
             {
@@ -582,8 +584,80 @@
             }
         }
 
+    }
+
+    /**
+     * Searches in the given table for a corresponding foreign key. If the given key
+     * has no name, then a foreign key to the same table with the same columns in the
+     * same order is searched. If the given key has a name, then the a corresponding
+     * key also needs to have the same name, or no name at all, but not a different one. 
+     * 
+     * @param table The table to search in
+     * @param fk    The original foreign key
+     * @return The corresponding foreign key if found
+     */
+    protected ForeignKey findCorrespondingForeignKey(Table table, ForeignKey fk)
+    {
+        boolean     caseMatters = getPlatformInfo().isUseDelimitedIdentifiers();
+        boolean     checkFkName = (fk.getName() != null) && (fk.getName().length() > 0);
+        Reference[] refs        = fk.getReferences();
+        ArrayList   curRefs     = new ArrayList();
+
+        for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++)
+        {
+            ForeignKey curFk          = table.getForeignKey(fkIdx);
+            boolean    checkCurFkName = checkFkName &&
+                                        (curFk.getName() != null) && (curFk.getName().length() > 0);
+
+            if ((!checkCurFkName || areEqual(fk.getName(), curFk.getName(), caseMatters)) &&
+                areEqual(fk.getForeignTableName(), curFk.getForeignTableName(), caseMatters))
+            {
+                curRefs.clear();
+                CollectionUtils.addAll(curRefs, curFk.getReferences());
+
+                // the order is not fixed, so we have to take this long way
+                if (curRefs.size() == refs.length)
+                {
+                    for (int refIdx = 0; refIdx < refs.length; refIdx++)
+                    {
+                        boolean found = false;
+
+                        for (int curRefIdx = 0; !found && (curRefIdx < curRefs.size()); curRefIdx++)
+                        {
+                            Reference curRef = (Reference)curRefs.get(curRefIdx);
+
+                            if ((caseMatters  && refs[refIdx].equals(curRef)) ||
+                                (!caseMatters && refs[refIdx].equalsIgnoreCase(curRef)))
+                            {
+                                curRefs.remove(curRefIdx);
+                                found = true;
+                            }
+                        }
+                    }
+                    if (curRefs.isEmpty())
+                    {
+                        return curFk;
+                    }
+                }
+            }
+        }
+        return null;
     } 
-    
+
+    /**
+     * Compares the two strings.
+     * 
+     * @param string1     The first string
+     * @param string2     The second string
+     * @param caseMatters Whether case matters in the comparison
+     * @return <code>true</code> if the string are equal
+     */
+    protected boolean areEqual(String string1, String string2, boolean caseMatters)
+    {
+        return (caseMatters  && string1.equals(string2)) ||
+               (!caseMatters && string1.equalsIgnoreCase(string2));
+    }
+
     /** 
      * Outputs the DDL to create the table along with any non-external constraints as well
      * as with external primary keys and indices (but not foreign keys).
@@ -1364,7 +1438,8 @@
         String  desiredDefault = desiredColumn.getDefaultValue();
         String  currentDefault = currentColumn.getDefaultValue();
         boolean defaultsEqual  = (desiredDefault == null) || desiredDefault.equals(currentDefault);
-        boolean sizeMatters    = getPlatformInfo().hasSize(currentColumn.getTypeCode());
+        boolean sizeMatters    = getPlatformInfo().hasSize(currentColumn.getTypeCode()) &&
+                                 (desiredColumn.getSize() != null);
 
         // We're comparing the jdbc type that corresponds to the native type for the
         // desired type, in order to avoid repeated altering of a perfectly valid column