Fix for DDLUTILS-214: Primary Key Column order lost (a problem if there are multiple Primary Keys)

git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@684633 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/ddlutils/platform/SqlBuilder.java b/src/main/java/org/apache/ddlutils/platform/SqlBuilder.java
index fb52445..33f8d2a 100644
--- a/src/main/java/org/apache/ddlutils/platform/SqlBuilder.java
+++ b/src/main/java/org/apache/ddlutils/platform/SqlBuilder.java
@@ -1052,12 +1052,15 @@
     }
 
     /**
-     * Creates the SQL for deleting an object from the specified table.
-     * If values are given then a concrete delete statement is created, otherwise an
-     * delete statement usable in a prepared statement is build.
+     * Creates the SQL for deleting an object from the specified table. Depending on
+     * the value of <code>genPlaceholders</code>, the generated SQL will contain
+     * prepared statement place holders or concrete values. Only those primary key
+     * columns wil be used that are present in the given map. If the map is null or
+     * completely empty, then the SQL will not have a WHERE clause. The SQL will contain
+     * the columns in the order defined in the table.
      * 
      * @param table           The table
-     * @param pkValues        The primary key values indexed by the column names, can be empty
+     * @param pkValues        The primary key columns to use, and optionally their values
      * @param genPlaceholders Whether to generate value placeholders for a
      *                        prepared statement
      * @return The delete sql
@@ -1071,26 +1074,30 @@
         if ((pkValues != null) && !pkValues.isEmpty())
         {
             buffer.append(" WHERE ");
-            for (Iterator it = pkValues.entrySet().iterator(); it.hasNext();)
+
+            Column[] pkCols = table.getPrimaryKeyColumns();
+
+            for (int pkColIdx = 0; pkColIdx < pkCols.length; pkColIdx++)
             {
-                Map.Entry entry  = (Map.Entry)it.next();
-                Column    column = table.findColumn((String)entry.getKey());
-    
-                if (addSep)
-                {
-                    buffer.append(" AND ");
+                Column column = pkCols[pkColIdx];
+
+                if (pkValues.containsKey(column.getName())) {
+                    if (addSep)
+                    {
+                        buffer.append(" AND ");
+                    }
+                    buffer.append(getDelimitedIdentifier(column.getName()));
+                    buffer.append(" = ");
+                    if (genPlaceholders)
+                    {
+                        buffer.append("?");
+                    }
+                    else
+                    {
+                        buffer.append(getValueAsString(column, pkValues.get(column.getName())));
+                    }
+                    addSep = true;
                 }
-                buffer.append(getDelimitedIdentifier(entry.getKey().toString()));
-                buffer.append(" = ");
-                if (genPlaceholders)
-                {
-                    buffer.append("?");
-                }
-                else
-                {
-                    buffer.append(column == null ? entry.getValue() : getValueAsString(column, entry.getValue()));
-                }
-                addSep = true;
             }
         }
         return buffer.toString();
diff --git a/src/test/java/org/apache/ddlutils/io/TestMisc.java b/src/test/java/org/apache/ddlutils/io/TestMisc.java
index 7c3da99..8b2c8d4 100644
--- a/src/test/java/org/apache/ddlutils/io/TestMisc.java
+++ b/src/test/java/org/apache/ddlutils/io/TestMisc.java
@@ -1058,11 +1058,11 @@
             "  <database xmlns='" + DatabaseIO.DDLUTILS_NAMESPACE + "' name='roundtriptest'>\n"+

             "    <table name='ad_sequence_no'>\n"+

             "      <column name='ad_sequence_id' required='true' type='NUMERIC' size='10'/>\n"+

-            "      <column name='year' required='true' type='VARCHAR' size='4' default='0000'/>\n"+

+            "      <column name='ad_year' required='true' type='VARCHAR' size='4' default='0000'/>\n"+

             "      <column name='ad_client_id' required='true' type='NUMERIC' size='10'/>\n"+

             "      <unique name='ad_sequence_no_key'>\n"+

             "        <unique-column name='ad_sequence_id'/>\n"+

-            "        <unique-column name='year'/>\n"+

+            "        <unique-column name='ad_year'/>\n"+

             "      </unique>\n"+

             "    </table>\n"+

             "</database>";

@@ -1157,4 +1157,62 @@
             }

         }

     }

+

+    /**

+     * Test for DDLUTILS-214.

+     */

+    public void testDdlUtils214() throws Exception

+    {

+        final String modelXml = 

+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+

+            "<database xmlns='" + DatabaseIO.DDLUTILS_NAMESPACE + "' name='roundtriptest'>\n"+

+            "  <table name='roundtrip1'>\n"+

+            "    <column name='pk1' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "    <column name='pk2' type='VARCHAR' primaryKey='true' required='true'/>\n"+

+            "  </table>\n"+

+            "  <table name='roundtrip2'>\n"+

+            "    <column name='pk2' type='VARCHAR' primaryKey='true' required='true'/>\n"+

+            "    <column name='pk1' type='INTEGER' primaryKey='true' required='true'/>\n"+

+            "  </table>\n"+

+            "</database>";

+

+        createDatabase(modelXml);

+

+        Database readModel = readModelFromDatabase("roundtriptest");

+        

+        assertEquals(getAdjustedModel(),

+                     readModel);

+

+        insertRow("roundtrip1", new Object[] { new Integer(1), "foo" });

+        insertRow("roundtrip1", new Object[] { new Integer(2), "bar" });

+        insertRow("roundtrip2", new Object[] { "foo", new Integer(1) });

+        insertRow("roundtrip2", new Object[] { "bar", new Integer(2) });

+

+        List beans1 = getRows("roundtrip1", "pk1");

+        List beans2 = getRows("roundtrip2", "pk1");

+

+        assertEquals(2, beans1.size());

+        assertEquals(2, beans2.size());

+        assertEquals(new Integer(1), beans1.get(0), "pk1");

+        assertEquals((Object)"foo",  beans1.get(0), "pk2");

+        assertEquals(new Integer(2), beans1.get(1), "pk1");

+        assertEquals((Object)"bar",  beans1.get(1), "pk2");

+        assertEquals(new Integer(1), beans2.get(0), "pk1");

+        assertEquals((Object)"foo",  beans2.get(0), "pk2");

+        assertEquals(new Integer(2), beans2.get(1), "pk1");

+        assertEquals((Object)"bar",  beans2.get(1), "pk2");

+

+        deleteRow("roundtrip1", new Object[] { new Integer(1), "foo" });

+        deleteRow("roundtrip2", new Object[] { "foo", new Integer(1) });

+

+        beans1 = getRows("roundtrip1", "pk1");

+        beans2 = getRows("roundtrip2", "pk1");

+

+        assertEquals(1, beans1.size());

+        assertEquals(1, beans2.size());

+        assertEquals(new Integer(2), beans1.get(0), "pk1");

+        assertEquals((Object)"bar",  beans1.get(0), "pk2");

+        assertEquals(new Integer(2), beans2.get(0), "pk1");

+        assertEquals((Object)"bar",  beans2.get(0), "pk2");

+    }

 }