FIX: optimized unique constraint handling for platforms that does support them on nullable columns (#1095)

This commit is contained in:
Roland Praml
2017-08-30 19:54:53 +12:00
committed by Rob Bygrave
parent f471961f06
commit d14529b602
4 changed files with 43 additions and 23 deletions
@@ -207,9 +207,12 @@ public class BaseTableDdl implements TableDdl {
String tableName = createTable.getName();
for (Column col : externalUnique) {
String uqName = col.getUniqueOneToOne();
if (uqName == null) {
uqName = col.getUnique();
}
String[] columnNames = {col.getName()};
write.apply()
.append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames))
.append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, Boolean.TRUE.equals(col.isNotnull())))
.endOfStatement();
write.dropAllForeignKeys()
@@ -221,7 +224,7 @@ public class BaseTableDdl implements TableDdl {
String uqName = constraint.getName();
String[] columnNames = StringHelper.delimitedToArray(constraint.getColumnNames(), ",", false);
write.apply()
.append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames))
.append(platformDdl.alterTableAddUniqueConstraint(tableName, uqName, columnNames, false)) // TODO: check if nullable
.endOfStatement();
write.dropAllForeignKeys()
@@ -421,9 +424,9 @@ public class BaseTableDdl implements TableDdl {
protected void writeCompoundUniqueConstraints(DdlBuffer apply, CreateTable createTable) throws IOException {
List<UniqueConstraint> uniqueConstraints = createTable.getUniqueConstraint();
boolean inlineUniqueCompound = platformDdl.isInlineUniqueOneToOne();
boolean inlineUniqueWhenNull = platformDdl.isInlineUniqueWhenNullable();
for (UniqueConstraint uniqueConstraint : uniqueConstraints) {
if (inlineUniqueCompound) {
if (inlineUniqueWhenNull) {
String uqName = uniqueConstraint.getName();
String[] columns = toColumnNamesSplit(uniqueConstraint.getColumnNames());
apply.append(",").newLine();
@@ -440,17 +443,18 @@ public class BaseTableDdl implements TableDdl {
*/
protected void writeUniqueConstraints(DdlBuffer apply, CreateTable createTable) throws IOException {
boolean inlineUniqueOneToOne = platformDdl.isInlineUniqueOneToOne();
boolean inlineUniqueWhenNullable = platformDdl.isInlineUniqueWhenNullable();
List<Column> columns = createTable.getColumn();
for (Column column : columns) {
if (hasValue(column.getUnique()) || (inlineUniqueOneToOne && hasValue(column.getUniqueOneToOne()))) {
// normal mechanism for adding unique constraint
inlineUniqueConstraintSingle(apply, column);
} else if (!inlineUniqueOneToOne && hasValue(column.getUniqueOneToOne())) {
// MsSqlServer specific mechanism for adding unique constraints (that allow nulls)
externalUnique.add(column);
if (hasValue(column.getUnique()) || hasValue(column.getUniqueOneToOne())) {
if (Boolean.TRUE.equals(column.isNotnull()) || inlineUniqueWhenNullable) {
// normal mechanism for adding unique constraint
inlineUniqueConstraintSingle(apply, column);
} else {
// MsSqlServer & DB2 specific mechanism for adding unique constraints (that allow nulls)
externalUnique.add(column);
}
}
}
}
@@ -834,9 +838,9 @@ public class BaseTableDdl implements TableDdl {
protected void addUniqueConstraint(DdlWrite writer, AlterColumn alter, String uqName) throws IOException {
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))
.append(platformDdl.alterTableAddUniqueConstraint(alter.getTableName(), uqName, cols, notNull))
.endOfStatement();
writer.dropAllForeignKeys()
@@ -10,6 +10,16 @@ public class DB2Ddl extends PlatformDdl {
public DB2Ddl(DatabasePlatform platform) {
super(platform);
this.identitySuffix = " generated by default as identity";
this.inlineUniqueWhenNullable = false;
}
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
if (notNull) {
return super.alterTableAddUniqueConstraint(tableName, uqName, columns, true);
} 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);
}
}
}
@@ -91,7 +91,7 @@ public class PlatformDdl {
/**
* Set false for MsSqlServer to allow multiple nulls for OneToOne mapping.
*/
protected boolean inlineUniqueOneToOne = true;
protected boolean inlineUniqueWhenNullable = true;
protected DbConstraintNaming naming;
@@ -371,7 +371,7 @@ public class PlatformDdl {
* <p>
* Overridden by MsSqlServer for specific null handling on unique constraints.
*/
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns) {
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
StringBuilder buffer = new StringBuilder(90);
buffer.append("alter table ").append(tableName).append(" add constraint ").append(uqName).append(" unique ");
@@ -401,11 +401,12 @@ public class PlatformDdl {
}
/**
* Return true if unique constraints for OneToOne can be inlined as normal.
* Returns false for MsSqlServer due to it's null handling for unique constraints.
* Return true if unique constraints for nullable columns can be inlined as normal.
* Returns false for MsSqlServer & DB2 due to it's not possible to to put a constraint
* on a nullable column
*/
public boolean isInlineUniqueOneToOne() {
return inlineUniqueOneToOne;
public boolean isInlineUniqueWhenNullable() {
return inlineUniqueWhenNullable;
}
/**
@@ -17,7 +17,7 @@ public class SqlServerDdl extends PlatformDdl {
this.foreignKeyRestrict = "";
this.alterTableIfExists = "";
this.addColumn = "add";
this.inlineUniqueOneToOne = false;
this.inlineUniqueWhenNullable = false;
this.columnSetDefault = "add default";
this.dropConstraintIfExists = "drop constraint";
this.historyDdl = new SqlServerHistoryDdl();
@@ -51,8 +51,13 @@ public class SqlServerDdl extends PlatformDdl {
* MsSqlServer specific null handling on unique constraints.
*/
@Override
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns) {
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, boolean notNull) {
if (notNull) {
return super.alterTableAddUniqueConstraint(tableName, uqName, columns, notNull);
}
if (uqName == null) {
throw new NullPointerException();
}
// issues#233
String start = "create unique nonclustered index " + uqName + " on " + tableName + "(";
StringBuilder sb = new StringBuilder(start);