Added support for reading the onUpdate and onDelete settings from a live database (for DDLUTILS-75)
git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@574795 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/java/database.dtd b/src/java/database.dtd
index 7f5382a..af57679 100644
--- a/src/java/database.dtd
+++ b/src/java/database.dtd
@@ -251,6 +251,7 @@
<dt>cascade</dt><dd>Delete the local row.</dd>
<dt>setnull</dt><dd>Set the local column to <code>NULL</code> which
effectively removes this specific foreign key relationship.</dd>
+ <dt>setdefault</dt><dd>Set the local column to its default value.</dd>
<dt>restrict</dt><dd>Different databases may interpret this value
differently, but usually it is synonymous with <code>none</code>.</dd>
<dt>none</dt><dd>The value of the local column remains unchanged.</dd>
@@ -259,8 +260,8 @@
<!ATTLIST foreign-key
foreignTable CDATA #REQUIRED
name CDATA #IMPLIED
- onUpdate (cascade | setnull | restrict | none) "none"
- onDelete (cascade | setnull | restrict | none) "none"
+ onUpdate (cascade | setnull | setdefault | restrict | none) "none"
+ onDelete (cascade | setnull | setdefault | restrict | none) "none"
>
<!--
diff --git a/src/java/org/apache/ddlutils/model/CascadeActionEnum.java b/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
index 22ed94b..c129f18 100644
--- a/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
+++ b/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
@@ -33,27 +33,34 @@
*/
public class CascadeActionEnum extends ValuedEnum
{
- /** The integer value for the enum value for a cascading change. */
- public static final int VALUE_CASCADE = 1;
- /** The integer value for the enum value for a set-null change. */
- public static final int VALUE_SETNULL = 2;
- /** The integer value for the enum value for a restrict change. */
- public static final int VALUE_RESTRICT = 3;
- /** The integer value for the enum value for no-change. */
- public static final int VALUE_NONE = 4;
+ /** The integer value for the enum value for a cascade action. */
+ public static final int VALUE_CASCADE = 1;
+ /** The integer value for the enum value for a set-null action. */
+ public static final int VALUE_SET_NULL = 2;
+ /** The integer value for the enum value for a set-null action. */
+ public static final int VALUE_SET_DEFAULT = 3;
+ /** The integer value for the enum value for a restrict action. */
+ public static final int VALUE_RESTRICT = 4;
+ /** The integer value for the enum value for no-action. */
+ public static final int VALUE_NONE = 5;
- /** The enum value for a cascade action which directs the database to change the value
- of local column to the new value of the referenced column when it changes. */
- public static final CascadeActionEnum CASCADE = new CascadeActionEnum("cascade", VALUE_CASCADE);
- /** The enum value for a cascade action which directs the database to set the local
- column to null when the referenced column changes. */
- public static final CascadeActionEnum SETNULL = new CascadeActionEnum("setnull", VALUE_SETNULL);
+ /** The enum value for a cascade action which directs the database to apply the change to
+ the referenced table also to this table. E.g. if the referenced row is deleted, then
+ the local one will also be deleted when this value is used for the onDelete action. */
+ public static final CascadeActionEnum CASCADE = new CascadeActionEnum("cascade", VALUE_CASCADE);
+ /** The enum value for a cascade action which directs the database to set the local columns
+ referenced by the foreign key to null when the referenced row changes/is deleted. */
+ public static final CascadeActionEnum SET_NULL = new CascadeActionEnum("setnull", VALUE_SET_NULL);
+ /** The enum value for a cascade action which directs the database to set the local columns
+ referenced by the foreign key to the default value when the referenced row changes/is deleted. */
+ public static final CascadeActionEnum SET_DEFAULT = new CascadeActionEnum("setdefault", VALUE_SET_DEFAULT);
/** The enum value for a cascade action which directs the database to restrict the change
- changes to the referenced column. The interpretation of this is database-dependent. */
- public static final CascadeActionEnum RESTRICT = new CascadeActionEnum("restrict", VALUE_RESTRICT);
- /** The enum value for a cascade action which directs the database to take do nothing
- to the local column when the value of the referenced column changes. */
- public static final CascadeActionEnum NONE = new CascadeActionEnum("none", VALUE_NONE);
+ changes to the referenced column. The interpretation of this is database-dependent, but it is
+ usually the same as {@link #NONE}. */
+ public static final CascadeActionEnum RESTRICT = new CascadeActionEnum("restrict", VALUE_RESTRICT);
+ /** The enum value for the cascade action that directs the database to not change the local column
+ when the value of the referenced column changes, only check the foreign key constraint. */
+ public static final CascadeActionEnum NONE = new CascadeActionEnum("none", VALUE_NONE);
/** Version id for this class as relevant for serialization. */
private static final long serialVersionUID = -6378050861446415790L;
diff --git a/src/java/org/apache/ddlutils/platform/JdbcModelReader.java b/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
index 8037afa..599a2bc 100644
--- a/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
+++ b/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
@@ -42,6 +42,7 @@
import org.apache.commons.logging.LogFactory;
import org.apache.ddlutils.Platform;
import org.apache.ddlutils.PlatformInfo;
+import org.apache.ddlutils.model.CascadeActionEnum;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
@@ -228,6 +229,8 @@
result.add(new MetaDataColumnDescriptor("FKTABLE_NAME", Types.VARCHAR));
result.add(new MetaDataColumnDescriptor("KEY_SEQ", Types.TINYINT, new Short((short)0)));
result.add(new MetaDataColumnDescriptor("FK_NAME", Types.VARCHAR));
+ result.add(new MetaDataColumnDescriptor("UPDATE_RULE", Types.TINYINT));
+ result.add(new MetaDataColumnDescriptor("DELETE_RULE", Types.TINYINT));
result.add(new MetaDataColumnDescriptor("PKCOLUMN_NAME", Types.VARCHAR));
result.add(new MetaDataColumnDescriptor("FKCOLUMN_NAME", Types.VARCHAR));
@@ -779,10 +782,15 @@
column.setName((String)values.get("COLUMN_NAME"));
column.setDefaultValue((String)values.get("COLUMN_DEF"));
column.setTypeCode(((Integer)values.get("DATA_TYPE")).intValue());
- column.setPrecisionRadix(((Integer)values.get("NUM_PREC_RADIX")).intValue());
- String size = (String)values.get("COLUMN_SIZE");
- int scale = ((Integer)values.get("DECIMAL_DIGITS")).intValue();
+ Integer precision = (Integer)values.get("NUM_PREC_RADIX");
+
+ if (precision != null)
+ {
+ column.setPrecisionRadix(precision.intValue());
+ }
+
+ String size = (String)values.get("COLUMN_SIZE");
if (size == null)
{
@@ -791,11 +799,14 @@
// we're setting the size after the precision and radix in case
// the database prefers to return them in the size value
column.setSize(size);
- if (scale != 0)
+
+ Integer scale = (Integer)values.get("DECIMAL_DIGITS");
+
+ if (scale != null)
{
// if there is a scale value, set it after the size (which probably did not contain
// a scale specification)
- column.setScale(scale);
+ column.setScale(scale.intValue());
}
column.setRequired("NO".equalsIgnoreCase(((String)values.get("IS_NULLABLE")).trim()));
column.setDescription((String)values.get("REMARKS"));
@@ -895,6 +906,8 @@
{
fk = new ForeignKey(fkName);
fk.setForeignTableName((String)values.get("PKTABLE_NAME"));
+ fk.setOnUpdate(convertAction((Short)values.get("UPDATE_RULE")));
+ fk.setOnDelete(convertAction((Short)values.get("DELETE_RULE")));
knownFks.put(fkName, fk);
}
@@ -910,6 +923,38 @@
}
/**
+ * Converts the JDBC action value (one of the <code>importKey</code> constants in the
+ * {@link DatabaseMetaData} class) to a {@link CascadeActionEnum}.
+ *
+ * @param jdbcActionValue The jdbc action value
+ * @return The enum value
+ */
+ protected CascadeActionEnum convertAction(Short jdbcActionValue)
+ {
+ CascadeActionEnum action = CascadeActionEnum.NONE;
+
+ if (jdbcActionValue != null)
+ {
+ switch (jdbcActionValue.shortValue())
+ {
+ case DatabaseMetaData.importedKeyCascade:
+ action = CascadeActionEnum.CASCADE;
+ break;
+ case DatabaseMetaData.importedKeySetNull:
+ action = CascadeActionEnum.SET_NULL;
+ break;
+ case DatabaseMetaData.importedKeySetDefault:
+ action = CascadeActionEnum.SET_DEFAULT;
+ break;
+ case DatabaseMetaData.importedKeyRestrict:
+ action = CascadeActionEnum.RESTRICT;
+ break;
+ }
+ }
+ return action;
+ }
+
+ /**
* Determines the indices for the indicated table.
*
* @param metaData The database meta data
diff --git a/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java b/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
index 6efabf9..4a66d01 100644
--- a/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
+++ b/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
@@ -115,17 +115,28 @@
}
if (foundIdx > 0)
{
+ Object result = null;
+
switch (_jdbcType)
{
case Types.BIT:
- return new Boolean(resultSet.getBoolean(foundIdx));
+ result = new Boolean(resultSet.getBoolean(foundIdx));
+ break;
case Types.INTEGER:
- return new Integer(resultSet.getInt(foundIdx));
+ result = new Integer(resultSet.getInt(foundIdx));
+ break;
case Types.TINYINT:
- return new Short(resultSet.getShort(foundIdx));
+ result = new Short(resultSet.getShort(foundIdx));
+ break;
default:
- return resultSet.getString(foundIdx);
+ result = resultSet.getString(foundIdx);
+ break;
}
+ if (resultSet.wasNull())
+ {
+ result = null;
+ }
+ return result;
}
else
{
diff --git a/src/java/org/apache/ddlutils/platform/SqlBuilder.java b/src/java/org/apache/ddlutils/platform/SqlBuilder.java
index 327648a..cce607e 100644
--- a/src/java/org/apache/ddlutils/platform/SqlBuilder.java
+++ b/src/java/org/apache/ddlutils/platform/SqlBuilder.java
@@ -63,6 +63,7 @@
import org.apache.ddlutils.alteration.RemovePrimaryKeyChange;
import org.apache.ddlutils.alteration.RemoveTableChange;
import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.model.CascadeActionEnum;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
@@ -2466,11 +2467,11 @@
{
for (int idx = 0; idx < table.getForeignKeyCount(); idx++)
{
- ForeignKey key = table.getForeignKey(idx);
+ ForeignKey foreignKey = table.getForeignKey(idx);
- 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
{
@@ -2478,16 +2479,18 @@
if (getPlatformInfo().isEmbeddedForeignKeysNamed())
{
print("CONSTRAINT ");
- printIdentifier(getForeignKeyName(table, key));
+ printIdentifier(getForeignKeyName(table, foreignKey));
print(" ");
}
print("FOREIGN KEY (");
- writeLocalReferences(key);
+ writeLocalReferences(foreignKey);
print(") REFERENCES ");
- printIdentifier(getTableName(database.findTable(key.getForeignTableName())));
+ printIdentifier(getTableName(database.findTable(foreignKey.getForeignTableName())));
print(" (");
- writeForeignReferences(key);
+ writeForeignReferences(foreignKey);
print(")");
+ writeForeignKeyOnDeleteAction(table, foreignKey);
+ writeForeignKeyOnUpdateAction(table, foreignKey);
}
}
}
@@ -2495,29 +2498,31 @@
/**
* Writes a single foreign key constraint using a alter table statement.
*
- * @param database The database model
- * @param table The table
- * @param key The foreign key
+ * @param database The database model
+ * @param table The table
+ * @param foreignKey The foreign key
*/
- protected void writeExternalForeignKeyCreateStmt(Database database, Table table, ForeignKey key) throws IOException
+ protected void writeExternalForeignKeyCreateStmt(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 CONSTRAINT ");
- printIdentifier(getForeignKeyName(table, key));
+ printIdentifier(getForeignKeyName(table, foreignKey));
print(" FOREIGN KEY (");
- writeLocalReferences(key);
+ writeLocalReferences(foreignKey);
print(") REFERENCES ");
- printIdentifier(getTableName(database.findTable(key.getForeignTableName())));
+ printIdentifier(getTableName(database.findTable(foreignKey.getForeignTableName())));
print(" (");
- writeForeignReferences(key);
+ writeForeignReferences(foreignKey);
print(")");
+ writeForeignKeyOnDeleteAction(table, foreignKey);
+ writeForeignKeyOnUpdateAction(table, foreignKey);
printEndOfStatement();
}
}
@@ -2557,6 +2562,70 @@
}
/**
+ * Writes the onDelete action for the given foreign key.
+ *
+ * @param table The table
+ * @param foreignKey The foreignkey
+ */
+ private void writeForeignKeyOnDeleteAction(Table table, ForeignKey foreignKey) throws IOException
+ {
+ if (foreignKey.getOnDelete() != CascadeActionEnum.NONE)
+ {
+ print(" ON DELETE ");
+ switch (foreignKey.getOnDelete().getValue())
+ {
+ case CascadeActionEnum.VALUE_CASCADE:
+ print("CASCADE");
+ break;
+ case CascadeActionEnum.VALUE_SET_NULL:
+ print("SET NULL");
+ break;
+ case CascadeActionEnum.VALUE_RESTRICT:
+ print("RESTRICT");
+ break;
+ case CascadeActionEnum.VALUE_NONE:
+ print("NO ACTION");
+ break;
+ default:
+ throw new ModelException("Unsupported cascade value '" + foreignKey.getOnDelete().getValue() +
+ "' for onDelete in foreign key in table " + table.getName());
+ }
+ }
+ }
+
+ /**
+ * Writes the onDelete action for the given foreign key.
+ *
+ * @param table The table
+ * @param foreignKey The foreignkey
+ */
+ private void writeForeignKeyOnUpdateAction(Table table, ForeignKey foreignKey) throws IOException
+ {
+ if (foreignKey.getOnUpdate() != CascadeActionEnum.NONE)
+ {
+ print(" ON UPDATE ");
+ switch (foreignKey.getOnUpdate().getValue())
+ {
+ case CascadeActionEnum.VALUE_CASCADE:
+ print("CASCADE");
+ break;
+ case CascadeActionEnum.VALUE_SET_NULL:
+ print("SET NULL");
+ break;
+ case CascadeActionEnum.VALUE_RESTRICT:
+ print("RESTRICT");
+ break;
+ case CascadeActionEnum.VALUE_NONE:
+ print("NO ACTION");
+ break;
+ default:
+ throw new ModelException("Unsupported cascade value '" + foreignKey.getOnUpdate().getValue() +
+ "' for onUpdate in foreign key in table " + table.getName());
+ }
+ }
+ }
+
+ /**
* Generates the statement to drop a foreignkey constraint from the database using an
* alter table statement.
*
diff --git a/src/test/org/apache/ddlutils/io/RoundtripTestBase.java b/src/test/org/apache/ddlutils/io/RoundtripTestBase.java
index f6308d6..0714473 100644
--- a/src/test/org/apache/ddlutils/io/RoundtripTestBase.java
+++ b/src/test/org/apache/ddlutils/io/RoundtripTestBase.java
@@ -35,6 +35,7 @@
import org.apache.ddlutils.dynabean.SqlDynaBean;
import org.apache.ddlutils.dynabean.SqlDynaClass;
import org.apache.ddlutils.dynabean.SqlDynaProperty;
+import org.apache.ddlutils.model.CascadeActionEnum;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.ForeignKey;
@@ -150,6 +151,26 @@
getPlatform().insert(getModel(), bean);
}
+
+ /**
+ * Deletes the specified row from the table.
+ *
+ * @param tableName The name of the table (case insensitive)
+ * @param pkColumnValues The values for the pk columns in order of definition
+ */
+ protected void deleteRow(String tableName, Object[] pkColumnValues)
+ {
+ Table table = getModel().findTable(tableName);
+ DynaBean bean = getModel().createDynaBeanFor(table);
+ Column[] pkColumns = table.getPrimaryKeyColumns();
+
+ for (int idx = 0; (idx < pkColumns.length) && (idx < pkColumnValues.length); idx++)
+ {
+ bean.set(pkColumns[idx].getName(), pkColumnValues[idx]);
+ }
+ getPlatform().delete(getModel(), bean);
+ }
+
/**
* Returns a "SELECT * FROM [table name]" statement. It also takes
* delimited identifier mode into account if enabled.
@@ -542,6 +563,28 @@
getPlatform().getSqlBuilder().shortenName(expected.getForeignTableName().toUpperCase(), getSqlBuilder().getMaxTableNameLength()),
getPlatform().getSqlBuilder().shortenName(actual.getForeignTableName().toUpperCase(), getSqlBuilder().getMaxTableNameLength()));
}
+ if ((expected.getOnUpdate() == CascadeActionEnum.NONE) || (expected.getOnUpdate() == CascadeActionEnum.RESTRICT))
+ {
+ assertTrue("Not the same onUpdate setting in foreign key "+actual.getName()+".",
+ (actual.getOnUpdate() == CascadeActionEnum.NONE) || (actual.getOnUpdate() == CascadeActionEnum.RESTRICT));
+ }
+ else
+ {
+ assertEquals("Not the same onUpdate setting in foreign key "+actual.getName()+".",
+ expected.getOnUpdate(),
+ actual.getOnUpdate());
+ }
+ if ((expected.getOnDelete() == CascadeActionEnum.NONE) || (expected.getOnDelete() == CascadeActionEnum.RESTRICT))
+ {
+ assertTrue("Not the same onDelete setting in foreign key "+actual.getName()+".",
+ (actual.getOnDelete() == CascadeActionEnum.NONE) || (actual.getOnDelete() == CascadeActionEnum.RESTRICT));
+ }
+ else
+ {
+ assertEquals("Not the same onDelete setting in foreign key "+actual.getName()+".",
+ expected.getOnDelete(),
+ actual.getOnDelete());
+ }
assertEquals("Not the same number of references in foreign key "+actual.getName()+".",
expected.getReferenceCount(),
actual.getReferenceCount());
diff --git a/src/test/org/apache/ddlutils/io/TestConstraints.java b/src/test/org/apache/ddlutils/io/TestConstraints.java
index e2fb5f4..a55f5e8 100644
--- a/src/test/org/apache/ddlutils/io/TestConstraints.java
+++ b/src/test/org/apache/ddlutils/io/TestConstraints.java
@@ -19,6 +19,8 @@
* under the License.
*/
+import java.util.List;
+
import org.apache.commons.lang.StringUtils;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.platform.sybase.SybasePlatform;
@@ -439,4 +441,115 @@
performConstraintsTest(modelXml, true);
}
+
+ /**
+ * Tests two tables with a foreign key with a restrict onDelete action.
+ */
+ public void testForeignKeyWithOnDeleteRestrict()
+ {
+ 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' onDelete='restrict'>\n"+
+ " <reference local='avalue' foreign='pk'/>\n"+
+ " </foreign-key>\n"+
+ " </table>\n"+
+ "</database>";
+
+ performConstraintsTest(modelXml, true);
+ }
+
+ /**
+ * Tests two tables with a foreign key with a cascade onDelete action.
+ */
+ public void testForeignKeyWithOnDeleteCascade()
+ {
+ 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' onDelete='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");
+
+ deleteRow("roundtrip_1", new Object[] { new Integer(1) });
+
+ beansTable1 = getRows("roundtrip_1");
+ beansTable2 = getRows("roundtrip_2");
+
+ assertEquals(0, beansTable1.size());
+ assertEquals(0, beansTable2.size());
+ }
+
+ /**
+ * Tests two tables with a foreign key with a cascade onDelete action.
+ */
+ public void testForeignKeyWithOnDeleteSetNull()
+ {
+ 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' onDelete='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");
+
+ deleteRow("roundtrip_1", new Object[] { new Integer(1) });
+
+ beansTable1 = getRows("roundtrip_1");
+ beansTable2 = getRows("roundtrip_2");
+
+ assertEquals(0, beansTable1.size());
+ assertEquals(1, beansTable2.size());
+ assertEquals(new Integer(5), beansTable2.get(0), "pk");
+ assertEquals((Object)null, beansTable2.get(0), "avalue");
+ }
}