Skip to content

Commit

Permalink
0003537: initial load create: Cascade Delete rule is not syncing as part
Browse files Browse the repository at this point in the history
of the create DDL
  • Loading branch information
philipmarzullo64 committed Feb 4, 2019
1 parent 301b98e commit 7ea5896
Show file tree
Hide file tree
Showing 20 changed files with 758 additions and 5 deletions.
Expand Up @@ -41,6 +41,7 @@
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.ForeignKey.ForeignKeyAction;
import org.jumpmind.db.model.IIndex;
import org.jumpmind.db.model.IndexColumn;
import org.jumpmind.db.model.NonUniqueIndex;
Expand Down Expand Up @@ -275,6 +276,10 @@ public static Table nextTable(XmlPullParser parser, String catalog, String schem
fk.setForeignTableCatalog(attributeValue);
} else if (attributeName.equalsIgnoreCase("foreignTableSchema")) {
fk.setForeignTableSchema(attributeValue);
} else if (attributeName.equalsIgnoreCase("foreignOnUpdateAction")) {
fk.setOnUpdateAction(ForeignKey.getForeignKeyActionByForeignKeyActionName(attributeValue));
} else if (attributeName.equalsIgnoreCase("foreignOnDeleteAction")) {
fk.setOnDeleteAction(ForeignKey.getForeignKeyActionByForeignKeyActionName(attributeValue));
}
}
table.addForeignKey(fk);
Expand Down Expand Up @@ -523,7 +528,13 @@ public static void write(Table table, Writer output) {
+ StringEscapeUtils.escapeXml(fk.getForeignTableCatalog() == null || fk.getForeignTableCatalog().equals(table.getCatalog())
? "" : fk.getForeignTableCatalog()) +
"\" foreignTableSchema=\"" + StringEscapeUtils.escapeXml(fk.getForeignTableSchema() == null ||
fk.getForeignTableSchema().equals(table.getSchema()) ? "" : fk.getForeignTableSchema()) + "\">\n");
fk.getForeignTableSchema().equals(table.getSchema()) ? "" : fk.getForeignTableSchema()) + "\""
+
writeForeignKeyOnUpdateClause(fk)
+
writeForeignKeyOnDeleteClause(fk)
+
">\n");

for (Reference ref : fk.getReferences()) {
output.write("\t\t\t<reference local=\"" + StringEscapeUtils.escapeXml(ref.getLocalColumnName())
Expand Down Expand Up @@ -557,4 +568,32 @@ public static void write(Table table, Writer output) {
throw new IoException(e);
}
}

public static String writeForeignKeyOnUpdateClause(ForeignKey fk) {
// No need to output action for RESTRICT and NO ACTION since that is the default in every database that supports foreign keys
StringBuilder sb = new StringBuilder();
if(! (fk.getOnUpdateAction().equals(ForeignKeyAction.UNDEFINED) ||
fk.getOnUpdateAction().equals(ForeignKeyAction.RESTRICT) ||
fk.getOnUpdateAction().equals(ForeignKeyAction.NOACTION)
))
{
sb.append(" foreignOnUpdateAction=\"" +
StringEscapeUtils.escapeXml(fk.getOnUpdateAction().getForeignKeyActionName()) + "\"");
}
return sb.toString();
}

public static String writeForeignKeyOnDeleteClause(ForeignKey fk) {
// No need to output action for RESTRICT and NO ACTION since that is the default in every database that supports foreign keys
StringBuilder sb = new StringBuilder();
if(! (fk.getOnDeleteAction().equals(ForeignKeyAction.UNDEFINED) ||
fk.getOnDeleteAction().equals(ForeignKeyAction.RESTRICT) ||
fk.getOnDeleteAction().equals(ForeignKeyAction.NOACTION)
))
{
sb.append(" foreignOnDeleteAction=\"" +
StringEscapeUtils.escapeXml(fk.getOnDeleteAction().getForeignKeyActionName()) + "\"");
}
return sb.toString();
}
}
97 changes: 94 additions & 3 deletions symmetric-db/src/main/java/org/jumpmind/db/model/ForeignKey.java
Expand Up @@ -22,17 +22,39 @@
import static org.apache.commons.lang.StringUtils.isNotBlank;

import java.io.Serializable;
import java.sql.DatabaseMetaData;
import java.util.HashSet;
import java.util.Iterator;

import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

/**
* Represents a database foreign key.
*/
public class ForeignKey implements Cloneable, Serializable {

public enum ForeignKeyAction {
UNDEFINED("UNDEFINED"),
CASCADE("CASCADE"),
NOACTION("NO ACTION"),
SETNULL("SET NULL"),
SETDEFAULT("SET DEFAULT"),
RESTRICT("RESTRICT");

private String foreignKeyActionName;

private ForeignKeyAction(String foreignKeyActionName) {
this.foreignKeyActionName = foreignKeyActionName;
}

public String getForeignKeyActionName() {
return foreignKeyActionName;
}
}


private static final long serialVersionUID = 1L;

Expand All @@ -55,6 +77,10 @@ public class ForeignKey implements Cloneable, Serializable {

private String foreignTableSchema;

private ForeignKeyAction onDeleteAction = ForeignKeyAction.UNDEFINED;

private ForeignKeyAction onUpdateAction = ForeignKeyAction.UNDEFINED;

/**
* Creates a new foreign key object that has no name.
*/
Expand Down Expand Up @@ -299,6 +325,8 @@ public Object clone() throws CloneNotSupportedException {
result.references = new ListOrderedSet();
result.foreignTableCatalog = foreignTableCatalog;
result.foreignTableSchema = foreignTableSchema;
result.onDeleteAction = getOnDeleteAction();
result.onUpdateAction = getOnUpdateAction();

for (Iterator<?> it = references.iterator(); it.hasNext();) {
result.references.add(((Reference) it.next()).clone());
Expand All @@ -324,6 +352,8 @@ public boolean equals(Object obj) {
builder.append(name, otherFk.name);
}
builder.append(foreignTableName, otherFk.foreignTableName);
builder.append(getOnDeleteAction(), otherFk.getOnDeleteAction());
builder.append(getOnUpdateAction(), otherFk.getOnUpdateAction());

builder.append(references.size(), otherFk.references.size());
for (int i = 0; i < references.size() && i < otherFk.references.size(); i++) {
Expand All @@ -337,7 +367,7 @@ public boolean equals(Object obj) {
}
}

/**
/**
* Compares this foreign key to the given one while ignoring the case of
* identifiers.
*
Expand All @@ -352,6 +382,12 @@ public boolean equalsIgnoreCase(ForeignKey otherFk) {

if ((!checkName || name.equalsIgnoreCase(otherFk.name))
&& foreignTableName.equalsIgnoreCase(otherFk.foreignTableName)) {
if(! otherFk.getOnDeleteAction().equals(getOnDeleteAction())) {
return false;
}
if(! otherFk.getOnUpdateAction().equals(getOnUpdateAction())) {
return false;
}
HashSet<Reference> otherRefs = new HashSet<Reference>();

otherRefs.addAll(otherFk.references);
Expand Down Expand Up @@ -392,6 +428,8 @@ public int hashCode() {
if (isNotBlank(name)) {
builder.append(name);
}
builder.append(getOnDeleteAction());
builder.append(getOnUpdateAction());
return builder.toHashCode();
}

Expand All @@ -410,6 +448,12 @@ public String toString() {
result.append("foreign table=");
result.append(getForeignTableName());
result.append("; ");
if(! getOnDeleteAction().equals(ForeignKeyAction.UNDEFINED)) {
result.append("ON DELETE " + getOnDeleteAction().getForeignKeyActionName()).append("; ");
}
if(! getOnUpdateAction().equals(ForeignKeyAction.UNDEFINED)) {
result.append("ON UPDATE " + getOnUpdateAction().getForeignKeyActionName()).append(";");
}
result.append(getReferenceCount());
result.append(" references]");

Expand All @@ -424,14 +468,21 @@ public String toString() {
public String toVerboseString() {
StringBuffer result = new StringBuffer();

result.append("ForeignK ky [");
result.append("Foreign key [");
if ((getName() != null) && (getName().length() > 0)) {
result.append("name=");
result.append(getName());
result.append("; ");
}
result.append("foreign table=");
result.append(getForeignTableName());
result.append(";");
if(! getOnDeleteAction().equals(ForeignKeyAction.UNDEFINED)) {
result.append(" ON DELETE " + getOnDeleteAction().getForeignKeyActionName());
}
if(! getOnUpdateAction().equals(ForeignKeyAction.UNDEFINED)) {
result.append(" ON UPDATE " + getOnUpdateAction().getForeignKeyActionName());
}
result.append("] references:");
for (int idx = 0; idx < getReferenceCount(); idx++) {
result.append(" ");
Expand All @@ -457,6 +508,46 @@ public void setForeignTableSchema(String foreignTableSchema) {
this.foreignTableSchema = foreignTableSchema;
}

public ForeignKeyAction getOnDeleteAction() {
return onDeleteAction;
}

public void setOnDeleteAction(ForeignKeyAction onDeleteAction) {
this.onDeleteAction = onDeleteAction;
}

public ForeignKeyAction getOnUpdateAction() {
return onUpdateAction;
}

public void setOnUpdateAction(ForeignKeyAction onUpdateAction) {
this.onUpdateAction = onUpdateAction;
}

public static ForeignKeyAction getForeignKeyAction(short importedKeyAction) {
switch(importedKeyAction) {
case DatabaseMetaData.importedKeyCascade:
return ForeignKeyAction.CASCADE;
case DatabaseMetaData.importedKeyNoAction:
return ForeignKeyAction.NOACTION;
case DatabaseMetaData.importedKeyRestrict:
return ForeignKeyAction.RESTRICT;
case DatabaseMetaData.importedKeySetDefault:
return ForeignKeyAction.SETDEFAULT;
case DatabaseMetaData.importedKeySetNull:
return ForeignKeyAction.SETNULL;
default:
return ForeignKeyAction.UNDEFINED;
}
}


public static ForeignKeyAction getForeignKeyActionByForeignKeyActionName(String foreignKeyActionName) throws IllegalArgumentException {
for(ForeignKeyAction action : ForeignKeyAction.values()) {
if(StringUtils.equals(foreignKeyActionName, action.getForeignKeyActionName())) {
return action;
}
}
throw new IllegalArgumentException("Unknown ForeignKeyAction: " + foreignKeyActionName);
}

}
Expand Up @@ -58,6 +58,7 @@
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.ForeignKey.ForeignKeyAction;
import org.jumpmind.db.model.IIndex;
import org.jumpmind.db.model.IndexColumn;
import org.jumpmind.db.model.ModelException;
Expand Down Expand Up @@ -2398,6 +2399,7 @@ protected void writeEmbeddedForeignKeysStmt(Table table, StringBuilder ddl) {
ddl.append(" (");
writeForeignReferences(key, ddl);
ddl.append(")");
writeCascadeAttributesForForeignKey(key, ddl);
}
}
}
Expand Down Expand Up @@ -2449,9 +2451,41 @@ protected void writeExternalForeignKeyCreateStmt(Database database, Table table,
ddl.append(" (");
writeForeignReferences(key, ddl);
ddl.append(")");
writeCascadeAttributesForForeignKey(key, ddl);
printEndOfStatement(ddl);
}
}

protected void writeCascadeAttributesForForeignKey(ForeignKey key, StringBuilder ddl) {
writeCascadeAttributesForForeignKeyDelete(key, ddl);
writeCascadeAttributesForForeignKeyUpdate(key, ddl);
}

protected void writeCascadeAttributesForForeignKeyDelete(ForeignKey key, StringBuilder ddl) {
// No need to output action for RESTRICT and NO ACTION since that is the default in every database that supports foreign keys
if(! (
key.getOnDeleteAction().equals(ForeignKeyAction.UNDEFINED) ||
key.getOnDeleteAction().equals(ForeignKeyAction.RESTRICT) ||
key.getOnDeleteAction().equals(ForeignKeyAction.NOACTION)
)
)
{
ddl.append(" ON DELETE " + key.getOnDeleteAction().getForeignKeyActionName());
}
}

protected void writeCascadeAttributesForForeignKeyUpdate(ForeignKey key, StringBuilder ddl) {
// No need to output action for RESTRICT and NO ACTION since that is the default in every database that supports foreign keys
if(! (
key.getOnUpdateAction().equals(ForeignKeyAction.UNDEFINED) ||
key.getOnUpdateAction().equals(ForeignKeyAction.RESTRICT) ||
key.getOnUpdateAction().equals(ForeignKeyAction.NOACTION)
)
)
{
ddl.append(" ON UPDATE " + key.getOnUpdateAction().getForeignKeyActionName());
}
}

/**
* Writes a list of local references for the given foreign key.
Expand Down
Expand Up @@ -577,4 +577,10 @@ protected void processColumnChange(Table sourceTable, Table targetTable, Column
protected String createUniqueIdentifier() {
return new UID().toString().replace(':', '_').replace('-', '_');
}

@Override
protected void writeCascadeAttributesForForeignKey(ForeignKey key, StringBuilder ddl) {
// Sybase does not support cascade actions
return;
}
}
Expand Up @@ -33,9 +33,11 @@
import org.jumpmind.db.alter.TableChange;
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.IIndex;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.db.model.ForeignKey.ForeignKeyAction;
import org.jumpmind.db.platform.AbstractDdlBuilder;
import org.jumpmind.db.platform.DatabaseNamesConstants;
import org.jumpmind.db.platform.PlatformUtils;
Expand Down Expand Up @@ -297,4 +299,12 @@ protected void writeReorgStmt(Table table, StringBuilder ddl) {
ddl.append(getFullyQualifiedTableNameShorten(table));
ddl.append("')");
}

@Override
protected void writeCascadeAttributesForForeignKeyUpdate(ForeignKey key, StringBuilder ddl) {
// DB2 only supports RESTRICT and NO ACTION for ON UPDATE
if(key.getOnUpdateAction().equals(ForeignKeyAction.RESTRICT) || key.getOnUpdateAction().equals(ForeignKeyAction.NOACTION)) {
super.writeCascadeAttributesForForeignKeyUpdate(key, ddl);
}
}
}
Expand Up @@ -28,9 +28,11 @@
import org.jumpmind.db.model.Column;
import org.jumpmind.db.model.ColumnTypes;
import org.jumpmind.db.model.Database;
import org.jumpmind.db.model.ForeignKey;
import org.jumpmind.db.model.IIndex;
import org.jumpmind.db.model.Table;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.db.model.ForeignKey.ForeignKeyAction;
import org.jumpmind.db.platform.AbstractDdlBuilder;
import org.jumpmind.db.platform.DatabaseNamesConstants;
import org.jumpmind.db.platform.PlatformUtils;
Expand Down Expand Up @@ -169,4 +171,20 @@ protected void processChange(Database currentModel, Database desiredModel,
change.apply(currentModel, delimitedIdentifierModeOn);
}

@Override
protected void writeCascadeAttributesForForeignKeyUpdate(ForeignKey key, StringBuilder ddl) {
// Derby does not support ON UPDATE SET DEFAULT
if(! key.getOnUpdateAction().equals(ForeignKeyAction.SETDEFAULT)) {
super.writeCascadeAttributesForForeignKeyUpdate(key, ddl);
}
}

@Override
protected void writeCascadeAttributesForForeignKeyDelete(ForeignKey key, StringBuilder ddl) {
// Derby does not support ON DELETE SET DEFAULT
if(! key.getOnDeleteAction().equals(ForeignKeyAction.SETDEFAULT)) {
super.writeCascadeAttributesForForeignKeyDelete(key, ddl);
}
}

}

0 comments on commit 7ea5896

Please sign in to comment.