Added equivalence for on delete/on update settings
git-svn-id: https://svn.apache.org/repos/asf/db/ddlutils/trunk@894556 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/ddlutils/PlatformInfo.java b/src/main/java/org/apache/ddlutils/PlatformInfo.java
index e1b04a7..b414ae6 100644
--- a/src/main/java/org/apache/ddlutils/PlatformInfo.java
+++ b/src/main/java/org/apache/ddlutils/PlatformInfo.java
@@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -180,6 +181,12 @@
/** Contains the supported ON DELETE actions. */
private HashSet _supportedOnDeleteActions = new HashSet();
+ /** Contains for each ON UPDATE action the list of equivalent actions. */
+ private HashMap _equivalentOnUpdateActions = new HashMap();
+
+ /** Contains for each ON DELETE action the list of equivalent actions. */
+ private HashMap _equivalentOnDeleteActions = new HashMap();
+
/**
* Creates a new platform info object.
*/
@@ -1276,4 +1283,92 @@
{
_defaultOnDeleteAction = defaultOnDeleteAction;
}
+
+ /**
+ * Registers the given pair of ON UPDATE actions to be equivalent. Equivalent actions will not
+ * cause a foreign key to be changed/recreated when altering a database.
+ *
+ * @param actionA The first action
+ * @param actionB The second action
+ */
+ public void addEquivalentOnUpdateActions(CascadeActionEnum actionA, CascadeActionEnum actionB)
+ {
+ if (!actionA.equals(actionB))
+ {
+ Set actionsEquivalentToActionA = (Set)_equivalentOnUpdateActions.get(actionA);
+ Set actionsEquivalentToActionB = (Set)_equivalentOnUpdateActions.get(actionB);
+
+ if (actionsEquivalentToActionA == null)
+ {
+ actionsEquivalentToActionA = new HashSet();
+ _equivalentOnUpdateActions.put(actionA, actionsEquivalentToActionA);
+ }
+ if (actionsEquivalentToActionB == null)
+ {
+ actionsEquivalentToActionB = new HashSet();
+ _equivalentOnUpdateActions.put(actionB, actionsEquivalentToActionB);
+ }
+ actionsEquivalentToActionA.add(actionB);
+ actionsEquivalentToActionB.add(actionA);
+ }
+ }
+
+ /**
+ * Determiones whether the two ON UPDATE actions are equivalent. Equivalent actions will not
+ * cause a foreign key to be changed/recreated when altering a database.
+ *
+ * @param actionA The first action
+ * @param actionB The second action
+ * @return <code>true</code> if the two actions are equivalent
+ */
+ public boolean areEquivalentOnUpdateActions(CascadeActionEnum actionA, CascadeActionEnum actionB)
+ {
+ Set actionsEquivalentToActionA = (Set)_equivalentOnUpdateActions.get(actionA);
+
+ return actionsEquivalentToActionA == null ? false : actionsEquivalentToActionA.contains(actionB);
+ }
+
+ /**
+ * Registers the given pair of ON DELETE actions to be equivalent. Equivalent actions will not
+ * cause a foreign key to be changed/recreated when altering a database.
+ *
+ * @param actionA The first action
+ * @param actionB The second action
+ */
+ public void addEquivalentOnDeleteActions(CascadeActionEnum actionA, CascadeActionEnum actionB)
+ {
+ if (!actionA.equals(actionB))
+ {
+ Set actionsEquivalentToActionA = (Set)_equivalentOnDeleteActions.get(actionA);
+ Set actionsEquivalentToActionB = (Set)_equivalentOnDeleteActions.get(actionB);
+
+ if (actionsEquivalentToActionA == null)
+ {
+ actionsEquivalentToActionA = new HashSet();
+ _equivalentOnDeleteActions.put(actionA, actionsEquivalentToActionA);
+ }
+ if (actionsEquivalentToActionB == null)
+ {
+ actionsEquivalentToActionB = new HashSet();
+ _equivalentOnDeleteActions.put(actionB, actionsEquivalentToActionB);
+ }
+ actionsEquivalentToActionA.add(actionB);
+ actionsEquivalentToActionB.add(actionA);
+ }
+ }
+
+ /**
+ * Determiones whether the two ON DELETE actions are equivalent. Equivalent actions will not
+ * cause a foreign key to be changed/recreated when altering a database.
+ *
+ * @param actionA The first action
+ * @param actionB The second action
+ * @return <code>true</code> if the two actions are equivalent
+ */
+ public boolean areEquivalentOnDeleteActions(CascadeActionEnum actionA, CascadeActionEnum actionB)
+ {
+ Set actionsEquivalentToActionA = (Set)_equivalentOnDeleteActions.get(actionA);
+
+ return actionsEquivalentToActionA == null ? false : actionsEquivalentToActionA.contains(actionB);
+ }
}
diff --git a/src/main/java/org/apache/ddlutils/alteration/ModelComparator.java b/src/main/java/org/apache/ddlutils/alteration/ModelComparator.java
index 13817dd..3a88eef 100644
--- a/src/main/java/org/apache/ddlutils/alteration/ModelComparator.java
+++ b/src/main/java/org/apache/ddlutils/alteration/ModelComparator.java
@@ -373,6 +373,7 @@
tableDefinitionChanges.addAll(checkForAddedColumns(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
tableDefinitionChanges.addAll(checkForPrimaryKeyChanges(sourceModel, sourceTable, intermediateModel, intermediateTable, targetModel, targetTable));
+ // TOOD: check for foreign key changes (on delete/on update)
if (!tableDefinitionChanges.isEmpty())
{
if ((_tableDefCangePredicate == null) || _tableDefCangePredicate.areSupported(tmpTable, tableDefinitionChanges))
diff --git a/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java b/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
index ee72b14..667b635 100644
--- a/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
+++ b/src/main/java/org/apache/ddlutils/platform/JdbcModelReader.java
@@ -933,12 +933,11 @@
CascadeActionEnum onUpdateAction = convertAction((Short)values.get("UPDATE_RULE"));
CascadeActionEnum onDeleteAction = convertAction((Short)values.get("DELETE_RULE"));
- // Some JDBC drivers lie and return actions that the DB not actually supports
- if ((onUpdateAction == null) || !getPlatformInfo().isActionSupportedForOnUpdate(onUpdateAction))
+ if (onUpdateAction == null)
{
onUpdateAction = getPlatformInfo().getDefaultOnUpdateAction();
}
- if ((onDeleteAction == null) || !getPlatformInfo().isActionSupportedForOnDelete(onDeleteAction))
+ if (onDeleteAction == null)
{
onDeleteAction = getPlatformInfo().getDefaultOnDeleteAction();
}
diff --git a/src/main/java/org/apache/ddlutils/platform/derby/DerbyPlatform.java b/src/main/java/org/apache/ddlutils/platform/derby/DerbyPlatform.java
index 1f7e09a..aa32e44 100644
--- a/src/main/java/org/apache/ddlutils/platform/derby/DerbyPlatform.java
+++ b/src/main/java/org/apache/ddlutils/platform/derby/DerbyPlatform.java
@@ -64,8 +64,11 @@
info.addNativeTypeMapping(Types.DOUBLE, "DOUBLE");
info.addNativeTypeMapping(Types.FLOAT, "DOUBLE", Types.DOUBLE);
info.setSupportedOnUpdateActions(new CascadeActionEnum[] { CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT });
+ info.setDefaultOnUpdateAction(CascadeActionEnum.NONE);
+ info.addEquivalentOnUpdateActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
info.setSupportedOnDeleteActions(new CascadeActionEnum[] { CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT,
CascadeActionEnum.CASCADE, CascadeActionEnum.SET_NULL });
+ info.setDefaultOnDeleteAction(CascadeActionEnum.NONE);
setSqlBuilder(new DerbyBuilder(this));
setModelReader(new DerbyModelReader(this));
diff --git a/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java b/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java
index ada4af1..6af9a2d 100644
--- a/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java
+++ b/src/main/java/org/apache/ddlutils/platform/mssql/MSSqlPlatform.java
@@ -77,7 +77,9 @@
info.setIdentityColumnAutomaticallyRequired(true);
info.setMultipleIdentityColumnsSupported(false);
info.setSupportedOnUpdateActions(new CascadeActionEnum[] { CascadeActionEnum.CASCADE, CascadeActionEnum.NONE });
+ info.addEquivalentOnUpdateActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
info.setSupportedOnDeleteActions(new CascadeActionEnum[] { CascadeActionEnum.CASCADE, CascadeActionEnum.NONE });
+ info.addEquivalentOnDeleteActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
info.addNativeTypeMapping(Types.ARRAY, "IMAGE", Types.LONGVARBINARY);
// BIGINT will be mapped back to BIGINT by the model reader
diff --git a/src/main/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java b/src/main/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java
index 4795c3c..2b27338 100644
--- a/src/main/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java
+++ b/src/main/java/org/apache/ddlutils/platform/oracle/Oracle8Platform.java
@@ -74,6 +74,7 @@
info.setPrimaryKeyColumnAutomaticallyRequired(true);
info.setSupportedOnUpdateActions(new CascadeActionEnum[] { CascadeActionEnum.NONE });
info.setSupportedOnDeleteActions(new CascadeActionEnum[] { CascadeActionEnum.CASCADE, CascadeActionEnum.SET_NULL, CascadeActionEnum.NONE });
+ info.addEquivalentOnDeleteActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
// Note that the back-mappings are partially done by the model reader, not the driver
info.addNativeTypeMapping(Types.ARRAY, "BLOB", Types.BLOB);
diff --git a/src/main/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java b/src/main/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java
index d651915..e3b2a60 100644
--- a/src/main/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java
+++ b/src/main/java/org/apache/ddlutils/platform/sapdb/SapDbPlatform.java
@@ -67,9 +67,10 @@
info.setMultipleIdentityColumnsSupported(false);
info.setCommentPrefix("/*");
info.setCommentSuffix("*/");
- info.setSupportedOnUpdateActions(new CascadeActionEnum[] { CascadeActionEnum.NONE });
- info.setDefaultOnDeleteAction(CascadeActionEnum.RESTRICT);
info.setSupportedOnDeleteActions(new CascadeActionEnum[] { CascadeActionEnum.CASCADE, CascadeActionEnum.RESTRICT, CascadeActionEnum.SET_DEFAULT, CascadeActionEnum.SET_NULL, CascadeActionEnum.NONE });
+ info.addEquivalentOnDeleteActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
+ info.setSupportedOnUpdateActions(new CascadeActionEnum[] { CascadeActionEnum.NONE });
+ info.addEquivalentOnUpdateActions(CascadeActionEnum.NONE, CascadeActionEnum.RESTRICT);
// BIGINT is also handled by the model reader
// Unfortunately there is no way to distinguish between REAL, and FLOAT/DOUBLE when
diff --git a/src/test/java/org/apache/ddlutils/TestAgainstLiveDatabaseBase.java b/src/test/java/org/apache/ddlutils/TestAgainstLiveDatabaseBase.java
index 36cde33..49125b5 100644
--- a/src/test/java/org/apache/ddlutils/TestAgainstLiveDatabaseBase.java
+++ b/src/test/java/org/apache/ddlutils/TestAgainstLiveDatabaseBase.java
@@ -53,7 +53,6 @@
import org.apache.ddlutils.io.DataReader;
import org.apache.ddlutils.io.DataToDatabaseSink;
import org.apache.ddlutils.io.DatabaseIO;
-import org.apache.ddlutils.model.CascadeActionEnum;
import org.apache.ddlutils.model.CloneHelper;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
@@ -1312,35 +1311,12 @@
getPlatform().getSqlBuilder().shortenName(actual.getForeignTableName().toUpperCase(), getSqlBuilder().getMaxTableNameLength()));
}
- CascadeActionEnum realExpectedOnUpdateAction = expected.getOnUpdate();
- CascadeActionEnum realActualOnUpdateAction = actual.getOnUpdate();
-
- if (!getPlatformInfo().isActionSupportedForOnUpdate(realExpectedOnUpdateAction) || (realExpectedOnUpdateAction == CascadeActionEnum.NONE))
- {
- realExpectedOnUpdateAction = getPlatformInfo().getDefaultOnUpdateAction();
- }
- if (!getPlatformInfo().isActionSupportedForOnUpdate(realActualOnUpdateAction) || (realActualOnUpdateAction == CascadeActionEnum.NONE))
- {
- realActualOnUpdateAction = getPlatformInfo().getDefaultOnUpdateAction();
- }
- assertEquals("Not the same onUpdate setting in foreign key "+actual.getName()+".",
- realExpectedOnUpdateAction,
- realActualOnUpdateAction);
-
- CascadeActionEnum realExpectedOnDeleteAction = expected.getOnDelete();
- CascadeActionEnum realActualOnDeleteAction = actual.getOnDelete();
-
- if (!getPlatformInfo().isActionSupportedForOnDelete(realExpectedOnDeleteAction) || (realExpectedOnDeleteAction == CascadeActionEnum.NONE))
- {
- realExpectedOnDeleteAction = getPlatformInfo().getDefaultOnDeleteAction();
- }
- if (!getPlatformInfo().isActionSupportedForOnDelete(realActualOnDeleteAction) || (realActualOnDeleteAction == CascadeActionEnum.NONE))
- {
- realActualOnDeleteAction = getPlatformInfo().getDefaultOnDeleteAction();
- }
- assertEquals("Not the same onDelete setting in foreign key "+actual.getName()+".",
- realExpectedOnDeleteAction,
- realActualOnDeleteAction);
+ assertTrue("Not the same onUpdate setting in foreign key "+actual.getName()+": expected = "+expected.getOnUpdate()+", actual = "+actual.getOnUpdate(),
+ expected.getOnUpdate().equals(actual.getOnUpdate()) ||
+ getPlatformInfo().areEquivalentOnUpdateActions(expected.getOnUpdate(), actual.getOnUpdate()));
+ assertTrue("Not the same onDelete setting in foreign key "+actual.getName()+": expected = "+expected.getOnDelete()+", actual = "+actual.getOnDelete(),
+ expected.getOnDelete().equals(actual.getOnDelete()) ||
+ getPlatformInfo().areEquivalentOnDeleteActions(expected.getOnDelete(), actual.getOnDelete()));
assertEquals("Not the same number of references in foreign key "+actual.getName()+".",
expected.getReferenceCount(),
diff --git a/src/test/resources/jdbc.properties.db2 b/src/test/resources/jdbc.properties.db2
index 4ddf2b2..2464fd5 100644
--- a/src/test/resources/jdbc.properties.db2
+++ b/src/test/resources/jdbc.properties.db2
@@ -26,6 +26,6 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=com.ibm.db2.jcc.DB2Driver
-datasource.url=jdbc:db2://192.168.129.134:50000/ddlutils
+datasource.url=jdbc:db2://192.168.129.133:50000/ddlutils
datasource.username=ddlutils
datasource.password=ddlutils
diff --git a/src/test/resources/jdbc.properties.firebird b/src/test/resources/jdbc.properties.firebird
index f02cffa..03fa361 100644
--- a/src/test/resources/jdbc.properties.firebird
+++ b/src/test/resources/jdbc.properties.firebird
@@ -29,7 +29,7 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=org.firebirdsql.jdbc.FBDriver
-datasource.url=jdbc:firebirdsql://192.168.129.129/C:/Program Files/Firebird/Firebird_2_0/data/ddlutils.fdb
+datasource.url=jdbc:firebirdsql://192.168.129.133/C:/Program Files/Firebird/Firebird_2_0/data/ddlutils.fdb
datasource.username=SYSDBA
datasource.password=masterkey
diff --git a/src/test/resources/jdbc.properties.maxdb b/src/test/resources/jdbc.properties.maxdb
index 1f88a04..8d88ea1 100644
--- a/src/test/resources/jdbc.properties.maxdb
+++ b/src/test/resources/jdbc.properties.maxdb
@@ -29,6 +29,6 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=com.sap.dbtech.jdbc.DriverSapDB
-datasource.url=jdbc:sapdb://192.168.129.134/MAXDB1
+datasource.url=jdbc:sapdb://192.168.129.133/MAXDB1
datasource.username=ddlutils
datasource.password=ddlutils
diff --git a/src/test/resources/jdbc.properties.oracle10 b/src/test/resources/jdbc.properties.oracle10
index 30932d8..1af9e9a 100644
--- a/src/test/resources/jdbc.properties.oracle10
+++ b/src/test/resources/jdbc.properties.oracle10
@@ -29,7 +29,7 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=oracle.jdbc.driver.OracleDriver
-datasource.url=jdbc:oracle:thin:@192.168.129.134:1521:XE
+datasource.url=jdbc:oracle:thin:@192.168.129.133:1521:XE
datasource.username=ddlutils
datasource.password=ddlutils
diff --git a/src/test/resources/jdbc.properties.postgresql b/src/test/resources/jdbc.properties.postgresql
index c5332bc..67d9bb9 100644
--- a/src/test/resources/jdbc.properties.postgresql
+++ b/src/test/resources/jdbc.properties.postgresql
@@ -29,7 +29,7 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=org.postgresql.Driver
-datasource.url=jdbc:postgresql://192.168.129.134/ddlutils
+datasource.url=jdbc:postgresql://192.168.129.133/ddlutils
datasource.username=ddlutils
datasource.password=ddlutils
diff --git a/src/test/resources/jdbc.properties.sqlserver2005 b/src/test/resources/jdbc.properties.sqlserver2005
index 0746a89..a9a665d 100644
--- a/src/test/resources/jdbc.properties.sqlserver2005
+++ b/src/test/resources/jdbc.properties.sqlserver2005
@@ -26,7 +26,7 @@
datasource.class=org.apache.commons.dbcp.BasicDataSource
datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
-datasource.url=jdbc:sqlserver://192.168.129.134;databaseName=ddlutils;selectMethod=cursor
+datasource.url=jdbc:sqlserver://192.168.129.133;databaseName=ddlutils;selectMethod=cursor
datasource.username=ddlutils
datasource.password=ddlutils