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


Reply via email to