diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java
index 93a900b30..ac5f64557 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java
@@ -6,7 +6,9 @@ import io.ebeaninternal.dbmigration.ddlgeneration.platform.PlatformDdl;
import io.ebeaninternal.dbmigration.migration.AddColumn;
import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
import io.ebeaninternal.dbmigration.migration.AddTableComment;
+import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
+import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.ChangeSet;
import io.ebeaninternal.dbmigration.migration.CreateIndex;
import io.ebeaninternal.dbmigration.migration.CreateTable;
@@ -59,6 +61,10 @@ public class BaseDdlHandler implements DdlHandler {
generate(writer, (AddHistoryTable) change);
} else if (change instanceof DropHistoryTable) {
generate(writer, (DropHistoryTable) change);
+ } else if (change instanceof AddUniqueConstraint) {
+ generate(writer, (AddUniqueConstraint) change);
+ } else if (change instanceof AlterForeignKey) {
+ generate(writer, (AlterForeignKey) change);
} else {
throw new IllegalArgumentException("Unsupported change: " + change);
}
@@ -125,4 +131,13 @@ public class BaseDdlHandler implements DdlHandler {
tableDdl.generate(writer, dropIndex);
}
+ @Override
+ public void generate(DdlWrite writer, AddUniqueConstraint constraint) throws IOException {
+ tableDdl.generate(writer, constraint);
+ }
+
+ @Override
+ public void generate(DdlWrite writer, AlterForeignKey alterForeignKey) throws IOException {
+ tableDdl.generate(writer, alterForeignKey);
+ }
}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java
index f49cefbb1..9a693640f 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java
@@ -3,7 +3,9 @@ package io.ebeaninternal.dbmigration.ddlgeneration;
import io.ebeaninternal.dbmigration.migration.AddColumn;
import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
import io.ebeaninternal.dbmigration.migration.AddTableComment;
+import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
+import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.ChangeSet;
import io.ebeaninternal.dbmigration.migration.CreateIndex;
import io.ebeaninternal.dbmigration.migration.CreateTable;
@@ -41,6 +43,10 @@ public interface DdlHandler {
void generate(DdlWrite writer, DropIndex dropIndex) throws IOException;
+ void generate(DdlWrite writer, AddUniqueConstraint constraint) throws IOException;
+
+ void generate(DdlWrite writer, AlterForeignKey alterForeignKey) throws IOException;
+
void generateProlog(DdlWrite write) throws IOException;
void generateEpilog(DdlWrite write) throws IOException;
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java
index f938b0b89..3ea2eacad 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java
@@ -3,7 +3,9 @@ package io.ebeaninternal.dbmigration.ddlgeneration;
import io.ebeaninternal.dbmigration.migration.AddColumn;
import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
import io.ebeaninternal.dbmigration.migration.AddTableComment;
+import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
+import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.CreateIndex;
import io.ebeaninternal.dbmigration.migration.CreateTable;
import io.ebeaninternal.dbmigration.migration.DropColumn;
@@ -69,6 +71,16 @@ public interface TableDdl {
void generate(DdlWrite writer, DropIndex dropIndex) throws IOException;
/**
+ * Write add unique constraint.
+ */
+ void generate(DdlWrite writer, AddUniqueConstraint constraint) throws IOException;
+
+ /**
+ * Writes alter foreign key statements.
+ * @throws IOException
+ */
+ void generate(DdlWrite writer, AlterForeignKey alterForeignKey) throws IOException;
+
/**
* Generate any extra DDL such as stored procedures or TableValueParameters.
*/
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java
index 455c802e8..abe8dfbbd 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java
@@ -13,7 +13,9 @@ import io.ebeaninternal.dbmigration.ddlgeneration.platform.util.IndexSet;
import io.ebeaninternal.dbmigration.migration.AddColumn;
import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
import io.ebeaninternal.dbmigration.migration.AddTableComment;
+import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
+import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.Column;
import io.ebeaninternal.dbmigration.migration.CreateIndex;
import io.ebeaninternal.dbmigration.migration.CreateTable;
@@ -330,7 +332,7 @@ public class BaseTableDdl implements TableDdl {
}
String[] columnNames = {col.getName()};
write.apply()
- .append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, Boolean.TRUE.equals(col.isNotnull())))
+ .append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, Boolean.TRUE.equals(col.isNotnull()) ? null : columnNames))
.endOfStatement();
write.dropAllForeignKeys()
@@ -340,9 +342,10 @@ public class BaseTableDdl implements TableDdl {
for (UniqueConstraint constraint : externalCompoundUnique) {
String uqName = constraint.getName();
- String[] columnNames = StringHelper.delimitedToArray(constraint.getColumnNames(), ",", false);
+ String[] columnNames = SplitColumns.split(constraint.getColumnNames());
+ String[] nullableColumns = SplitColumns.split(constraint.getNullableColumns());
write.apply()
- .append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, false)) // TODO: check if nullable
+ .append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, nullableColumns))
.endOfStatement();
write.dropAllForeignKeys()
@@ -639,6 +642,40 @@ public class BaseTableDdl implements TableDdl {
.append(platformDdl.dropIndex(dropIndex.getIndexName(), dropIndex.getTableName()))
.endOfStatement();
}
+ @Override
+ public void generate(DdlWrite writer, AddUniqueConstraint constraint) throws IOException {
+
+ if (DdlHelp.isDropConstraint(constraint.getColumnNames())) {
+ String ddl = platformDdl.alterTableDropUniqueConstraint(constraint.getTableName(), constraint.getConstraintName());
+ if (hasValue(ddl)) {
+ writer.apply().append(ddl).endOfStatement();
+ }
+ } else {
+ String[] cols = SplitColumns.split(constraint.getColumnNames());
+ String[] nullableColumns = SplitColumns.split(constraint.getNullableColumns());
+ String ddl = platformDdl.alterTableAddUniqueConstraint(constraint.getTableName(), constraint.getConstraintName(), cols, nullableColumns);
+ if (hasValue(ddl)) {
+ writer.apply().append(ddl).endOfStatement();
+ }
+ }
+ }
+
+ @Override
+ public void generate(DdlWrite writer, AlterForeignKey alterForeignKey) throws IOException {
+ if (DdlHelp.isDropForeignKey(alterForeignKey.getColumnNames())) {
+
+ String ddl = platformDdl.alterTableDropForeignKey(alterForeignKey.getTableName(),
+ alterForeignKey.getName());
+ if (hasValue(ddl)) {
+ writer.apply().append(ddl).endOfStatement();
+ }
+ } else {
+ String ddl = platformDdl.alterTableAddForeignKey(new WriteForeignKey(alterForeignKey));
+ if (hasValue(ddl)) {
+ writer.apply().append(ddl).endOfStatement();
+ }
+ }
+ }
/**
* Add add history table DDL.
@@ -932,7 +969,7 @@ public class BaseTableDdl implements TableDdl {
String[] cols = {alter.getColumnName()};
boolean notNull = alter.isNotnull() != null ? alter.isNotnull() : Boolean.TRUE.equals(alter.isNotnull());
writer.apply()
- .append(platformDdl.alterTableAddUniqueConstraint(alter.getTableName(), uqName, cols, notNull))
+ .append(platformDdl.alterTableAddUniqueConstraint(alter.getTableName(), uqName, cols, notNull ? null : cols))
.endOfStatement();
writer.dropAllForeignKeys()
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java
index 0a8659421..17a463d60 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java
@@ -18,12 +18,12 @@ public class DB2Ddl extends PlatformDdl {
}
@Override
- public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
- if (notNull) {
- return super.alterTableAddUniqueConstraint(tableName, uqName, columns, true);
+ public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) {
+ if (nullableColumns == null || nullableColumns.length == 0) {
+ return super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns);
} else {
// Hmm: Complex workaround: https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/unique_where_not_null_indexes26?lang=en
- return "-- NOT SUPPORTED " + super.alterTableAddUniqueConstraint(tableName, uqName, columns, true);
+ return "-- NOT SUPPORTED " + super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns);
}
}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java
index 1ee1ff53b..ceb531530 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java
@@ -5,18 +5,35 @@ public class DdlHelp {
public static final String DROP_COMMENT = "DROP COMMENT";
- /**
- * Return true if the default value is the special DROP DEFAULT value.
- */
- public static boolean isDropDefault(String defaultValue) {
- return DROP_DEFAULT.equals(defaultValue);
- }
+ public static final String DROP_CONSTRAINT = "DROP CONSTRAINT";
+
+ public static final String DROP_FOREIGN_KEY = "DROP FOREIGN KEY";
/**
* Return true if the default value is the special DROP DEFAULT value.
*/
- public static boolean isDropComment(String comment) {
- return DROP_COMMENT.equals(comment);
+ public static boolean isDropDefault(String value) {
+ return DROP_DEFAULT.equals(value);
}
+ /**
+ * Return true if the default value is the special DROP COMMENT value.
+ */
+ public static boolean isDropComment(String value) {
+ return DROP_COMMENT.equals(value);
+ }
+
+ /**
+ * Return true if the default value is the special DROP CONSTRAINT value.
+ */
+ public static boolean isDropConstraint(String value) {
+ return DROP_CONSTRAINT.equals(value);
+ }
+
+ /**
+ * Return true if the default value is the special DROP FOREIGN KEY value.
+ */
+ public static boolean isDropForeignKey(String value) {
+ return DROP_FOREIGN_KEY.equals(value);
+ }
}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java
index 6e80e4d72..0baf8ab4e 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/MySqlDdl.java
@@ -108,6 +108,15 @@ public class MySqlDdl extends PlatformDdl {
*/
@Override
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) throws IOException {
+ if (DdlHelp.isDropComment(tableComment)) {
+ tableComment = "";
+ }
apply.append(String.format("alter table %s comment = '%s'", tableName, tableComment)).endOfStatement();
}
+
+ @Override
+ public void addColumnComment(DdlBuffer apply, String table, String column, String comment) throws IOException {
+ // alter comment currently not supported as it requires to repeat whole column definition
+ }
+
}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/Oracle10Ddl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/Oracle10Ddl.java
index 2071a94e2..9481660ea 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/Oracle10Ddl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/Oracle10Ddl.java
@@ -22,6 +22,16 @@ public class Oracle10Ddl extends PlatformDdl {
this.identitySuffix = " generated always as identity";
}
+ @Override
+ public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) {
+ if (nullableColumns == null || nullableColumns.length == 0) {
+ return super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns);
+ } else {
+ // Hmm: https://stackoverflow.com/questions/11893134/oracle-create-unique-index-but-ignore-nulls
+ return "-- NOT YET IMPLEMENTED: " + super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns);
+ }
+ }
+
@Override
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
// do nothing, no on update clause for oracle
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java
index af7d41453..db37454c6 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java
@@ -432,7 +432,7 @@ public class PlatformDdl {
*
* Overridden by MsSqlServer for specific null handling on unique constraints.
*/
- public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
+ public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) {
StringBuilder buffer = new StringBuilder(90);
buffer.append("alter table ").append(tableName).append(" add constraint ").append(uqName).append(" unique ");
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java
index 843abad99..6b094f9d9 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java
@@ -63,9 +63,9 @@ public class SqlServerDdl extends PlatformDdl {
* MsSqlServer specific null handling on unique constraints.
*/
@Override
- public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
- if (notNull) {
- return super.alterTableAddUniqueConstraint(tableName, uqName, columns, notNull);
+ public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) {
+ if (nullableColumns == null || nullableColumns.length == 0) {
+ return super.alterTableAddUniqueConstraint(tableName, uqName, columns, nullableColumns);
}
if (uqName == null) {
throw new NullPointerException();
@@ -82,7 +82,7 @@ public class SqlServerDdl extends PlatformDdl {
}
sb.append(") where");
String sep = " ";
- for (String column : columns) {
+ for (String column : nullableColumns) {
sb.append(sep).append(column).append(" is not null");
sep = " and ";
}
diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/WriteForeignKey.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/WriteForeignKey.java
index f9fab239d..e2ed698f0 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/WriteForeignKey.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/WriteForeignKey.java
@@ -2,6 +2,7 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.annotation.ConstraintMode;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
+import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
import io.ebeaninternal.dbmigration.migration.Column;
import io.ebeaninternal.dbmigration.migration.ForeignKey;
@@ -37,6 +38,17 @@ class WriteForeignKey {
this.onUpdate = modeOf(key.getOnUpdate());
}
+ WriteForeignKey(AlterForeignKey key) {
+ this.tableName = key.getTableName();
+ this.indexName = key.getIndexName();
+ this.fkName = key.getName();
+ this.cols = toCols(key.getColumnNames());
+ this.refTableName = key.getRefTableName();
+ this.refCols = toCols(key.getRefColumnNames());
+ this.onDelete = modeOf(key.getOnDelete());
+ this.onUpdate = modeOf(key.getOnUpdate());
+ }
+
WriteForeignKey(String tableName, Column column) {
this.tableName = tableName;
this.indexName = column.getForeignKeyIndex();
diff --git a/src/main/java/io/ebeaninternal/dbmigration/migration/AddUniqueConstraint.java b/src/main/java/io/ebeaninternal/dbmigration/migration/AddUniqueConstraint.java
new file mode 100644
index 000000000..8ed14b23f
--- /dev/null
+++ b/src/main/java/io/ebeaninternal/dbmigration/migration/AddUniqueConstraint.java
@@ -0,0 +1,137 @@
+package io.ebeaninternal.dbmigration.migration;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
The following schema fragment specifies the expected content contained within this class.
+ *