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/09/14 08:26:01 UTC

svn commit: r575556 - in /db/ddlutils/trunk/src: java/org/apache/ddlutils/ java/org/apache/ddlutils/platform/ test/org/apache/ddlutils/io/

Author: tomdz
Date: Thu Sep 13 23:26:00 2007
New Revision: 575556

URL: http://svn.apache.org/viewvc?rev=575556&view=rev
Log:
Added onUpdate tests

Modified:
    db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
    db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java
    db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestConstraints.java

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java?rev=575556&r1=575555&r2=575556&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/Platform.java Thu Sep 13 23:26:00 2007
@@ -841,6 +841,27 @@
     public void update(Connection connection, Database model, DynaBean dynaBean) throws DatabaseOperationException;
 
     /**
+     * Updates the row identified by the given <code>oldDynaBean</code> in the database with the
+     * values in <code>newDynaBean</code>.
+     * 
+     * @param model       The database model to use
+     * @param oldDynaBean The bean identifying the row (which means the primary key fields need to be specified)
+     * @param newDynaBean The bean containing the new data
+     */
+    public void update(Database model, DynaBean oldDynaBean, DynaBean newDynaBean) throws DatabaseOperationException;
+
+    /**
+     * Updates the row identified by the given <code>oldDynaBean</code> in the database with the
+     * values in <code>newDynaBean</code>.
+     * 
+     * @param connection  The database connection
+     * @param model       The database model to use
+     * @param oldDynaBean The bean identifying the row (which means the primary key fields need to be specified)
+     * @param newDynaBean The bean containing the new data
+     */
+    public void update(Connection connection, Database model, DynaBean oldDynaBean, DynaBean newDynaBean) throws DatabaseOperationException;
+
+    /**
      * Returns the sql for deleting the given bean from the database.
      * 
      * @param model    The database model to use

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java?rev=575556&r1=575555&r2=575556&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/PlatformImplBase.java Thu Sep 13 23:26:00 2007
@@ -1618,6 +1618,87 @@
     /**
      * {@inheritDoc}
      */
+    public void update(Connection connection, Database model, DynaBean oldDynaBean, DynaBean newDynaBean) throws DatabaseOperationException
+    {
+        SqlDynaClass      dynaClass   = model.getDynaClassFor(oldDynaBean);
+        SqlDynaProperty[] primaryKeys = dynaClass.getPrimaryKeyProperties();
+
+        if (!dynaClass.getTable().equals(model.getDynaClassFor(newDynaBean)))
+        {
+            throw new DatabaseOperationException("The old and new dyna beans need to be for the same table");
+        }
+        if (primaryKeys.length == 0)
+        {
+            _log.info("Cannot update instances of type " + dynaClass + " because it has no primary keys");
+            return;
+        }
+
+        SqlDynaProperty[] properties = dynaClass.getSqlDynaProperties();
+        String            sql        = createUpdateSql(model, dynaClass, primaryKeys, properties, null);
+        PreparedStatement statement  = null;
+
+        if (_log.isDebugEnabled())
+        {
+            _log.debug("About to execute SQL: " + sql);
+        }
+        try
+        {
+            beforeUpdate(connection, dynaClass.getTable());
+
+            statement = connection.prepareStatement(sql);
+
+            int sqlIndex = 1;
+
+            for (int idx = 0; idx < properties.length; idx++)
+            {
+                setObject(statement, sqlIndex++, newDynaBean, properties[idx]);
+            }
+            for (int idx = 0; idx < primaryKeys.length; idx++)
+            {
+                setObject(statement, sqlIndex++, oldDynaBean, primaryKeys[idx]);
+            }
+
+            int count = statement.executeUpdate();
+
+            afterUpdate(connection, dynaClass.getTable());
+
+            if (count != 1)
+            {
+                _log.warn("Attempted to insert a single row " + newDynaBean +
+                         " into table " + dynaClass.getTableName() +
+                         " but changed " + count + " row(s)");
+            }
+        }
+        catch (SQLException ex)
+        {
+            throw new DatabaseOperationException("Error while updating in the database", ex);
+        }
+        finally
+        {
+            closeStatement(statement);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void update(Database model, DynaBean oldDynaBean, DynaBean newDynaBean) throws DatabaseOperationException
+    {
+        Connection connection = borrowConnection();
+
+        try
+        {
+            update(connection, model, oldDynaBean, newDynaBean);
+        }
+        finally
+        {
+            returnConnection(connection);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public void update(Connection connection, Database model, DynaBean dynaBean) throws DatabaseOperationException
     {
         SqlDynaClass      dynaClass   = model.getDynaClassFor(dynaBean);

Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/SqlBuilder.java?rev=575556&r1=575555&r2=575556&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 Sep 13 23:26:00 2007
@@ -1526,6 +1526,25 @@
      */
     public String getUpdateSql(Table table, Map columnValues, boolean genPlaceholders)
     {
+        return getUpdateSql(table, columnValues, columnValues, genPlaceholders);
+    }
+
+    /**
+     * Creates the SQL for updating an object in the specified table.
+     * If values are given then a concrete update statement is created, otherwise an
+     * update statement usable in a prepared statement is build.
+     * 
+     * @param table           The table
+     * @param oldColumnValues Contains the column values to identify the row to update 
+     * @param columnValues    Contains the values for the columns to update, and should also
+     *                        contain the primary key values to identify the object to update
+     *                        in case <code>genPlaceholders</code> is <code>false</code> 
+     * @param genPlaceholders Whether to generate value placeholders for a
+     *                        prepared statement (both for the pk values and the object values)
+     * @return The update sql
+     */
+    public String getUpdateSql(Table table, Map oldColumnValues, Map newColumnValues, boolean genPlaceholders)
+    {
         StringBuffer buffer = new StringBuffer("UPDATE ");
         boolean      addSep = false;
 
@@ -1536,7 +1555,7 @@
         {
             Column column = table.getColumn(idx);
 
-            if (!column.isPrimaryKey() && columnValues.containsKey(column.getName()))
+            if (!column.isPrimaryKey() && newColumnValues.containsKey(column.getName()))
             {
                 if (addSep)
                 {
@@ -1550,7 +1569,7 @@
                 }
                 else
                 {
-                    buffer.append(getValueAsString(column, columnValues.get(column.getName())));
+                    buffer.append(getValueAsString(column, newColumnValues.get(column.getName())));
                 }
                 addSep = true;
             }
@@ -1561,7 +1580,7 @@
         {
             Column column = table.getColumn(idx);
 
-            if (column.isPrimaryKey() && columnValues.containsKey(column.getName()))
+            if (column.isPrimaryKey() && oldColumnValues.containsKey(column.getName()))
             {
                 if (addSep)
                 {
@@ -1575,7 +1594,7 @@
                 }
                 else
                 {
-                    buffer.append(getValueAsString(column, columnValues.get(column.getName())));
+                    buffer.append(getValueAsString(column, oldColumnValues.get(column.getName())));
                 }
                 addSep = true;
             }

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java?rev=575556&r1=575555&r2=575556&view=diff
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java Thu Sep 13 23:26:00 2007
@@ -151,6 +151,26 @@
         getPlatform().insert(getModel(), bean);
     }
 
+    /**
+     * Updates the row in the designated table.
+     * 
+     * @param tableName    The name of the table (case insensitive)
+     * @param oldBean      The bean representing the current row
+     * @param columnValues The values for the columns in order of definition
+     */
+    protected void updateRow(String tableName, DynaBean oldBean, Object[] columnValues)
+    {
+        Table    table = getModel().findTable(tableName);
+        DynaBean bean  = getModel().createDynaBeanFor(table);
+
+        for (int idx = 0; (idx < table.getColumnCount()) && (idx < columnValues.length); idx++)
+        {
+            Column column = table.getColumn(idx);
+
+            bean.set(column.getName(), columnValues[idx]);
+        }
+        getPlatform().update(getModel(), oldBean, bean);
+    }
 
     /**
      * Deletes the specified row from the table.

Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestConstraints.java
URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestConstraints.java?rev=575556&r1=575555&r2=575556&view=diff
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestConstraints.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestConstraints.java Thu Sep 13 23:26:00 2007
@@ -21,7 +21,9 @@
 
 import java.util.List;
 
+import org.apache.commons.beanutils.DynaBean;
 import org.apache.commons.lang.StringUtils;
+import org.apache.ddlutils.DdlUtilsException;
 import org.apache.ddlutils.model.Database;
 import org.apache.ddlutils.platform.sybase.SybasePlatform;
 
@@ -463,6 +465,26 @@
             "</database>";
 
         performConstraintsTest(modelXml, true);
+
+        insertRow("roundtrip_1", new Object[] { new Integer(1) });
+        insertRow("roundtrip_2", new Object[] { new Integer(5), new Integer(1) });
+
+        List beansTable1 = getRows("roundtrip_1");
+        List beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(1), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals(new Integer(1), beansTable2.get(0), "avalue");
+
+        try
+        {
+            deleteRow("roundtrip_1", new Object[] { new Integer(1) });
+            fail();
+        }
+        catch (DdlUtilsException ex)
+        {}
     }
 
     /**
@@ -598,6 +620,193 @@
             assertEquals(1, beansTable2.size());
             assertEquals(new Integer(5), beansTable2.get(0), "pk");
             assertEquals(new Integer(0), beansTable2.get(0), "avalue");
+        }
+    }
+
+    /**
+     * Tests two tables with a foreign key with a restrict onUpdate action. 
+     */
+    public void testForeignKeyWithOnUpdateRestrict()
+    {
+        final String modelXml = 
+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+            "<database name='roundtriptest'>\n"+
+            "  <table name='roundtrip_1'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "  </table>\n"+
+            "  <table name='roundtrip_2'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "    <column name='avalue' type='INTEGER' required='true'/>\n"+
+            "    <foreign-key foreignTable='roundtrip_1' onUpdate='restrict'>\n"+
+            "      <reference local='avalue' foreign='pk'/>\n"+
+            "    </foreign-key>\n"+
+            "  </table>\n"+
+            "</database>";
+
+        performConstraintsTest(modelXml, true);
+
+        insertRow("roundtrip_1", new Object[] { new Integer(1) });
+        insertRow("roundtrip_2", new Object[] { new Integer(5), new Integer(1) });
+
+        List beansTable1 = getRows("roundtrip_1");
+        List beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(1), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals(new Integer(1), beansTable2.get(0), "avalue");
+
+        try
+        {
+            updateRow("roundtrip_1", (DynaBean)beansTable1.get(0), new Object[] { new Integer(5) });
+            fail();
+        }
+        catch (DdlUtilsException ex)
+        {}
+    }
+
+    /**
+     * Tests two tables with a foreign key with a cascade onUpdate action. 
+     */
+    public void testForeignKeyWithOnUpdateCascade()
+    {
+        final String modelXml = 
+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+            "<database name='roundtriptest'>\n"+
+            "  <table name='roundtrip_1'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "  </table>\n"+
+            "  <table name='roundtrip_2'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "    <column name='avalue' type='INTEGER' required='true'/>\n"+
+            "    <foreign-key foreignTable='roundtrip_1' onUpdate='cascade'>\n"+
+            "      <reference local='avalue' foreign='pk'/>\n"+
+            "    </foreign-key>\n"+
+            "  </table>\n"+
+            "</database>";
+
+        performConstraintsTest(modelXml, true);
+
+        insertRow("roundtrip_1", new Object[] { new Integer(1) });
+        insertRow("roundtrip_2", new Object[] { new Integer(5), new Integer(1) });
+
+        List beansTable1 = getRows("roundtrip_1");
+        List beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(1), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals(new Integer(1), beansTable2.get(0), "avalue");
+
+        updateRow("roundtrip_1", (DynaBean)beansTable1.get(0), new Object[] { new Integer(2) });
+
+        beansTable1 = getRows("roundtrip_1");
+        beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(2), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals(new Integer(2), beansTable2.get(0), "avalue");
+    }
+
+    /**
+     * Tests two tables with a foreign key with a set-null onUpdate action. 
+     */
+    public void testForeignKeyWithOnUpdateSetNull()
+    {
+        final String modelXml = 
+            "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+            "<database name='roundtriptest'>\n"+
+            "  <table name='roundtrip_1'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "  </table>\n"+
+            "  <table name='roundtrip_2'>\n"+
+            "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+            "    <column name='avalue' type='INTEGER' required='false'/>\n"+
+            "    <foreign-key foreignTable='roundtrip_1' onUpdate='setnull'>\n"+
+            "      <reference local='avalue' foreign='pk'/>\n"+
+            "    </foreign-key>\n"+
+            "  </table>\n"+
+            "</database>";
+
+        performConstraintsTest(modelXml, true);
+
+        insertRow("roundtrip_1", new Object[] { new Integer(1) });
+        insertRow("roundtrip_2", new Object[] { new Integer(5), new Integer(1) });
+
+        List beansTable1 = getRows("roundtrip_1");
+        List beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(1), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals(new Integer(1), beansTable2.get(0), "avalue");
+
+        updateRow("roundtrip_1", (DynaBean)beansTable1.get(0), new Object[] { new Integer(2) });
+
+        beansTable1 = getRows("roundtrip_1");
+        beansTable2 = getRows("roundtrip_2");
+
+        assertEquals(1, beansTable1.size());
+        assertEquals(1, beansTable2.size());
+        assertEquals(new Integer(2), beansTable1.get(0), "pk");
+        assertEquals(new Integer(5), beansTable2.get(0), "pk");
+        assertEquals((Object)null, beansTable2.get(0), "avalue");
+    }
+
+    /**
+     * Tests two tables with a foreign key with a det-default onUpdate action. 
+     */
+    public void testForeignKeyWithOnUpdateSetDefault()
+    {
+        if (getPlatformInfo().isSetDefaultActionSupported())
+        {
+            final String modelXml = 
+                "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+                "<database name='roundtriptest'>\n"+
+                "  <table name='roundtrip_1'>\n"+
+                "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+                "  </table>\n"+
+                "  <table name='roundtrip_2'>\n"+
+                "    <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+                "    <column name='avalue' type='INTEGER' required='false' default='2'/>\n"+
+                "    <foreign-key foreignTable='roundtrip_1' onUpdate='setdefault'>\n"+
+                "      <reference local='avalue' foreign='pk'/>\n"+
+                "    </foreign-key>\n"+
+                "  </table>\n"+
+                "</database>";
+
+            performConstraintsTest(modelXml, true);
+    
+            insertRow("roundtrip_1", new Object[] { new Integer(1) });
+            insertRow("roundtrip_1", new Object[] { new Integer(2) });
+            insertRow("roundtrip_2", new Object[] { new Integer(5), new Integer(1) });
+    
+            List beansTable1 = getRows("roundtrip_1");
+            List beansTable2 = getRows("roundtrip_2");
+    
+            assertEquals(2, beansTable1.size());
+            assertEquals(1, beansTable2.size());
+            assertEquals(new Integer(1), beansTable1.get(0), "pk");
+            assertEquals(new Integer(2), beansTable1.get(1), "pk");
+            assertEquals(new Integer(5), beansTable2.get(0), "pk");
+            assertEquals(new Integer(1), beansTable2.get(0), "avalue");
+    
+            updateRow("roundtrip_1", (DynaBean)beansTable1.get(0), new Object[] { new Integer(0) });
+    
+            beansTable1 = getRows("roundtrip_1");
+            beansTable2 = getRows("roundtrip_2");
+    
+            assertEquals(2, beansTable1.size());
+            assertEquals(1, beansTable2.size());
+            assertEquals(new Integer(0), beansTable1.get(0), "pk");
+            assertEquals(new Integer(2), beansTable1.get(1), "pk");
+            assertEquals(new Integer(5), beansTable2.get(0), "pk");
+            assertEquals(new Integer(2), beansTable2.get(0), "avalue");
         }
     }
 }