Author: tomdz
Date: Tue Sep 11 23:21:40 2007
New Revision: 574795
URL: http://svn.apache.org/viewvc?rev=574795&view=rev
Log:
Added support for reading the onUpdate and onDelete settings from a live
database (for DDLUTILS-75)
Modified:
db/ddlutils/trunk/src/java/database.dtd
db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.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/database.dtd
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/database.dtd?rev=574795&r1=574794&r2=574795&view=diff
==============================================================================
Binary files - no diff available.
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java?rev=574795&r1=574794&r2=574795&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
(original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/CascadeActionEnum.java
Tue Sep 11 23:21:40 2007
@@ -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 [EMAIL PROTECTED] #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;
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java?rev=574795&r1=574794&r2=574795&view=diff
==============================================================================
---
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
(original)
+++
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/JdbcModelReader.java
Tue Sep 11 23:21:40 2007
@@ -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);
}
@@ -909,6 +922,38 @@
fk.addReference(ref);
}
+ /**
+ * Converts the JDBC action value (one of the <code>importKey</code>
constants in the
+ * [EMAIL PROTECTED] DatabaseMetaData} class) to a [EMAIL PROTECTED]
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.
*
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
URL:
http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java?rev=574795&r1=574794&r2=574795&view=diff
==============================================================================
---
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
(original)
+++
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/MetaDataColumnDescriptor.java
Tue Sep 11 23:21:40 2007
@@ -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
{
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=574795&r1=574794&r2=574795&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 Tue
Sep 11 23:21:40 2007
@@ -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();
}
}
@@ -2553,6 +2558,70 @@
print(", ");
}
printIdentifier(key.getReference(idx).getForeignColumnName());
+ }
+ }
+
+ /**
+ * 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());
+ }
}
}
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=574795&r1=574794&r2=574795&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
Tue Sep 11 23:21:40 2007
@@ -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.
@@ -541,6 +562,28 @@
assertEquals("Referenced table names do not match (ignoring
case).",
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(),
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=574795&r1=574794&r2=574795&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 Tue
Sep 11 23:21:40 2007
@@ -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;
@@ -438,5 +440,116 @@
"</database>";
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");
}
}