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");
}
}
}