#323 - DDL Generation support for foreign key cascade options

This commit is contained in:
Rob Bygrave
2018-02-19 22:24:37 +13:00
parent b8aa822a30
commit 40634412f5
31 changed files with 868 additions and 133 deletions
@@ -389,14 +389,7 @@ public class BaseTableDdl implements TableDdl {
protected void writeInlineForeignKey(DdlWrite write, Column column) throws IOException {
String references = column.getReferences();
int pos = references.lastIndexOf('.');
if (pos == -1) {
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
}
String refTableName = references.substring(0, pos);
String refColumnName = references.substring(pos + 1);
String fkConstraint = platformDdl.tableInlineForeignKey(new String[]{column.getName()}, refTableName, new String[]{refColumnName});
String fkConstraint = platformDdl.tableInlineForeignKey(new WriteForeignKey(null, column));
write.apply().append(",").newLine().append(" ").append(fkConstraint);
}
@@ -404,11 +397,7 @@ public class BaseTableDdl implements TableDdl {
List<ForeignKey> foreignKey = createTable.getForeignKey();
for (ForeignKey key : foreignKey) {
String refTableName = key.getRefTableName();
String[] cols = toColumnNamesSplit(key.getColumnNames());
String[] refColumns = toColumnNamesSplit(key.getRefColumnNames());
String fkConstraint = platformDdl.tableInlineForeignKey(cols, refTableName, refColumns);
String fkConstraint = platformDdl.tableInlineForeignKey(new WriteForeignKey(null, key));
write.apply().append(",").newLine().append(" ").append(fkConstraint);
}
}
@@ -433,61 +422,42 @@ public class BaseTableDdl implements TableDdl {
List<ForeignKey> foreignKey = createTable.getForeignKey();
for (ForeignKey key : foreignKey) {
String refTableName = key.getRefTableName();
String fkName = key.getName();
String[] cols = toColumnNamesSplit(key.getColumnNames());
String[] refColumns = toColumnNamesSplit(key.getRefColumnNames());
writeForeignKey(write, fkName, tableName, cols, refTableName, refColumns, key.getIndexName());
writeForeignKey(write, new WriteForeignKey(tableName, key));
}
}
protected void writeForeignKey(DdlWrite write, String tableName, Column column) throws IOException {
String fkName = column.getForeignKeyName();
String references = column.getReferences();
int pos = references.lastIndexOf('.');
if (pos == -1) {
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
}
String refTableName = references.substring(0, pos);
String refColumnName = references.substring(pos + 1);
String[] cols = {column.getName()};
String[] refCols = {refColumnName};
writeForeignKey(write, fkName, tableName, cols, refTableName, refCols, column.getForeignKeyIndex());
writeForeignKey(write, new WriteForeignKey(tableName, column));
}
protected void writeForeignKey(DdlWrite write, String fkName, String tableName, String[] columns, String refTable, String[] refColumns, String indexName) throws IOException {
protected void writeForeignKey(DdlWrite write, WriteForeignKey request) throws IOException {
tableName = lowerTableName(tableName);
String tableName = lowerTableName(request.table());
DdlBuffer fkeyBuffer = write.applyForeignKeys();
alterTableAddForeignKey(fkeyBuffer, fkName, tableName, columns, refTable, refColumns);
alterTableAddForeignKey(fkeyBuffer, request);
if (indexName != null) {
if (request.indexName() != null) {
// no matching unique constraint so add the index
fkeyBuffer.append(platformDdl.createIndex(indexName, tableName, columns)).endOfStatement();
fkeyBuffer.append(platformDdl.createIndex(request.indexName(), tableName, request.cols())).endOfStatement();
}
fkeyBuffer.end();
write.dropAllForeignKeys()
.append(platformDdl.alterTableDropForeignKey(tableName, fkName)).endOfStatement();
.append(platformDdl.alterTableDropForeignKey(tableName, request.fkName())).endOfStatement();
if (indexName != null) {
if (request.indexName() != null) {
write.dropAllForeignKeys()
.append(platformDdl.dropIndex(indexName, tableName)).endOfStatement();
.append(platformDdl.dropIndex(request.indexName(), tableName)).endOfStatement();
}
write.dropAllForeignKeys().end();
}
protected void alterTableAddForeignKey(DdlBuffer buffer, String fkName, String tableName, String[] columns, String refTable, String[] refColumns) throws IOException {
protected void alterTableAddForeignKey(DdlBuffer buffer, WriteForeignKey request) throws IOException {
String fkConstraint = platformDdl.alterTableAddForeignKey(tableName, fkName, columns, refTable, refColumns);
String fkConstraint = platformDdl.alterTableAddForeignKey(request);
if (fkConstraint != null && !fkConstraint.isEmpty()) {
buffer.append(fkConstraint).endOfStatement();
}
@@ -554,7 +524,7 @@ public class BaseTableDdl implements TableDdl {
for (UniqueConstraint uniqueConstraint : uniqueConstraints) {
if (inlineUniqueWhenNull) {
String uqName = uniqueConstraint.getName();
String[] columns = toColumnNamesSplit(uniqueConstraint.getColumnNames());
String[] columns = SplitColumns.split(uniqueConstraint.getColumnNames());
apply.append(",").newLine();
apply.append(" constraint ").append(uqName).append(" unique");
appendColumns(columns, apply);
@@ -625,13 +595,6 @@ public class BaseTableDdl implements TableDdl {
return cols;
}
/**
* Return as an array of string column names.
*/
protected String[] toColumnNamesSplit(String columns) {
return columns.split(",");
}
/**
* Convert the table lower case.
*/
@@ -662,7 +625,7 @@ public class BaseTableDdl implements TableDdl {
@Override
public void generate(DdlWrite writer, CreateIndex createIndex) throws IOException {
String[] cols = toColumnNamesSplit(createIndex.getColumns());
String[] cols = SplitColumns.split(createIndex.getColumns());
writer.apply()
.append(platformDdl.createIndex(createIndex.getIndexName(), createIndex.getTableName(), cols))
.endOfStatement();
@@ -931,22 +894,9 @@ public class BaseTableDdl implements TableDdl {
}
}
protected void alterColumnAddForeignKey(DdlWrite writer, AlterColumn alterColumn) throws IOException {
String tableName = alterColumn.getTableName();
String fkName = alterColumn.getForeignKeyName();
String[] cols = {alterColumn.getColumnName()};
String references = alterColumn.getReferences();
int pos = references.lastIndexOf('.');
if (pos == -1) {
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
}
String refTableName = references.substring(0, pos);
String refColumnName = references.substring(pos + 1);
String[] refCols = {refColumnName};
alterTableAddForeignKey(writer.apply(), fkName, tableName, cols, refTableName, refCols);
alterTableAddForeignKey(writer.apply(), new WriteForeignKey(alterColumn));
}
protected void alterColumnDropForeignKey(DdlWrite writer, AlterColumn alter) throws IOException {
@@ -1,5 +1,6 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.annotation.ConstraintMode;
import io.ebean.config.dbplatform.DatabasePlatform;
/**
@@ -14,7 +15,6 @@ public class Oracle10Ddl extends PlatformDdl {
this.dropConstraintIfExists = "drop constraint";
this.dropIndexIfExists = "drop index ";
this.dropTableCascade = " cascade constraints purge";
this.foreignKeyRestrict = "";
this.alterColumn = "modify";
this.columnSetNotnull = "not null";
this.columnSetNull = "null";
@@ -22,4 +22,20 @@ public class Oracle10Ddl extends PlatformDdl {
this.identitySuffix = " generated always as identity";
}
@Override
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
// do nothing, no on update clause for oracle
}
@Override
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
switch (mode) {
case SET_NULL:
case CASCADE:
super.appendForeignKeyMode(buffer, onMode, mode);
default:
// do nothing, defaults to RESTRICT effectively
}
}
}
@@ -1,11 +1,13 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.annotation.ConstraintMode;
import io.ebean.config.DbConstraintNaming;
import io.ebean.config.ServerConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbDefaultValue;
import io.ebean.config.dbplatform.DbIdentity;
import io.ebean.config.dbplatform.IdType;
import io.ebean.util.StringHelper;
import io.ebeaninternal.dbmigration.ddlgeneration.BaseDdlHandler;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
@@ -17,7 +19,6 @@ import io.ebeaninternal.dbmigration.migration.Column;
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
import io.ebeaninternal.dbmigration.migration.IdentityType;
import io.ebeaninternal.dbmigration.model.MTable;
import io.ebean.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,7 +63,8 @@ public class PlatformDdl {
*/
protected String dropSequenceIfExists = "drop sequence if exists ";
protected String foreignKeyRestrict = "on delete restrict on update restrict";
protected String foreignKeyOnDelete = "on delete";
protected String foreignKeyOnUpdate = "on update";
protected String identitySuffix = " auto_increment";
@@ -351,37 +353,68 @@ public class PlatformDdl {
/**
* Return the foreign key constraint when used inline with create table.
*/
public String tableInlineForeignKey(String[] columns, String refTable, String[] refColumns) {
public String tableInlineForeignKey(WriteForeignKey request) {
StringBuilder buffer = new StringBuilder(90);
buffer.append("foreign key");
appendColumns(columns, buffer);
buffer.append(" references ").append(lowerTableName(refTable));
appendColumns(refColumns, buffer);
appendWithSpace(foreignKeyRestrict, buffer);
appendColumns(request.cols(), buffer);
buffer.append(" references ").append(lowerTableName(request.refTable()));
appendColumns(request.refCols(), buffer);
appendForeignKeySuffix(request, buffer);
return buffer.toString();
}
/**
* Add foreign key.
*/
public String alterTableAddForeignKey(String tableName, String fkName, String[] columns, String refTable, String[] refColumns) {
public String alterTableAddForeignKey(WriteForeignKey request) {
StringBuilder buffer = new StringBuilder(90);
buffer
.append("alter table ").append(tableName)
.append(" add constraint ").append(fkName)
.append("alter table ").append(lowerTableName(request.table()))
.append(" add constraint ").append(request.fkName())
.append(" foreign key");
appendColumns(columns, buffer);
appendColumns(request.cols(), buffer);
buffer
.append(" references ")
.append(lowerTableName(refTable));
appendColumns(refColumns, buffer);
appendWithSpace(foreignKeyRestrict, buffer);
.append(lowerTableName(request.refTable()));
appendColumns(request.refCols(), buffer);
appendForeignKeySuffix(request, buffer);
return buffer.toString();
}
protected void appendForeignKeySuffix(WriteForeignKey request, StringBuilder buffer) {
appendForeignKeyOnDelete(buffer, withDefault(request.onDelete()));
appendForeignKeyOnUpdate(buffer, withDefault(request.onDelete()));
}
protected ConstraintMode withDefault(ConstraintMode mode) {
return (mode == null || mode == ConstraintMode.GLOBAL_DEFAULT) ? ConstraintMode.RESTRICT : mode;
}
protected void appendForeignKeyOnDelete(StringBuilder buffer, ConstraintMode mode) {
appendForeignKeyMode(buffer, foreignKeyOnDelete, mode);
}
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
appendForeignKeyMode(buffer, foreignKeyOnUpdate, mode);
}
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
buffer.append(" ").append(onMode).append(" ").append(translate(mode));
}
protected String translate(ConstraintMode mode) {
switch(mode) {
case SET_NULL: return "set null";
case SET_DEFAULT: return "set default";
case RESTRICT: return "restrict";
case CASCADE: return "cascade";
default:
throw new IllegalStateException("Unknown mode "+mode);
}
}
/**
* Drop a unique constraint from the table (Sometimes this is an index).
*/
@@ -3,8 +3,6 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import java.io.IOException;
/**
* DB2 platform specific DDL.
*/
@@ -17,17 +15,17 @@ public class SQLiteDdl extends PlatformDdl {
}
@Override
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) throws IOException {
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) {
// not supported
}
@Override
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) throws IOException {
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) {
// not supported
}
@Override
public String alterTableAddForeignKey(String tableName, String fkName, String[] columns, String refTable, String[] refColumns) {
public String alterTableAddForeignKey(WriteForeignKey request) {
// not supported
return null;
}
@@ -0,0 +1,12 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
public class SplitColumns {
/**
* Return as an array of string column names.
*/
public static String[] split(String columns) {
return columns.split(",");
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.annotation.ConstraintMode;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
@@ -14,7 +15,6 @@ public class SqlServerDdl extends PlatformDdl {
public SqlServerDdl(DatabasePlatform platform) {
super(platform);
this.identitySuffix = " identity(1,1)";
this.foreignKeyRestrict = "";
this.alterTableIfExists = "";
this.addColumn = "add";
this.inlineUniqueWhenNullable = false;
@@ -23,6 +23,13 @@ public class SqlServerDdl extends PlatformDdl {
this.historyDdl = new SqlServerHistoryDdl();
}
@Override
protected void appendForeignKeyMode(StringBuilder buffer, String onMode, ConstraintMode mode) {
if (mode != ConstraintMode.RESTRICT) {
super.appendForeignKeyMode(buffer, onMode, mode);
}
}
@Override
public String dropTable(String tableName) {
StringBuilder buffer = new StringBuilder();
@@ -0,0 +1,100 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.annotation.ConstraintMode;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
import io.ebeaninternal.dbmigration.migration.Column;
import io.ebeaninternal.dbmigration.migration.ForeignKey;
class WriteForeignKey {
private final String fkName;
private final String tableName;
private final String[] cols;
private String refTableName;
private String[] refCols;
private final String indexName;
private final ConstraintMode onDelete;
private final ConstraintMode onUpdate;
WriteForeignKey(AlterColumn alterColumn) {
this.tableName = alterColumn.getTableName();
this.indexName = alterColumn.getForeignKeyIndex();
this.fkName = alterColumn.getForeignKeyName();
this.cols = new String[]{alterColumn.getColumnName()};
setReferences(alterColumn.getReferences());
this.onDelete = modeOf(alterColumn.getForeignKeyOnDelete());
this.onUpdate = modeOf(alterColumn.getForeignKeyOnUpdate());
}
WriteForeignKey(String tableName, ForeignKey key) {
this.tableName = tableName;
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();
this.fkName = column.getForeignKeyName();
this.cols = new String[]{column.getName()};
setReferences(column.getReferences());
this.onDelete = modeOf(column.getForeignKeyOnDelete());
this.onUpdate = modeOf(column.getForeignKeyOnUpdate());
}
private void setReferences(String references) {
int pos = references.lastIndexOf('.');
if (pos == -1) {
throw new IllegalStateException("Expecting period '.' character for table.column split but not found in [" + references + "]");
}
this.refTableName = references.substring(0, pos);
String refColumnName = references.substring(pos + 1);
this.refCols = new String[]{refColumnName};
}
private String[] toCols(String columns) {
return SplitColumns.split(columns);
}
private ConstraintMode modeOf(String value) {
return (value == null) ? null : ConstraintMode.valueOf(value);
}
public String table() {
return tableName;
}
public String[] cols() {
return cols;
}
public String indexName() {
return indexName;
}
public String fkName() {
return fkName;
}
public String refTable() {
return refTableName;
}
public String[] refCols() {
return refCols;
}
public ConstraintMode onDelete() {
return onDelete;
}
public ConstraintMode onUpdate() {
return onUpdate;
}
}
@@ -1,14 +1,13 @@
package io.ebeaninternal.dbmigration.migration;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
@@ -40,6 +39,8 @@ import javax.xml.bind.annotation.XmlType;
* &lt;attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="dropForeignKey" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="dropForeignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
@@ -99,6 +100,10 @@ public class AlterColumn {
protected String foreignKeyName;
@XmlAttribute(name = "foreignKeyIndex")
protected String foreignKeyIndex;
@XmlAttribute(name = "foreignKeyOnDelete")
protected String foreignKeyOnDelete;
@XmlAttribute(name = "foreignKeyOnUpdate")
protected String foreignKeyOnUpdate;
@XmlAttribute(name = "dropForeignKey")
protected String dropForeignKey;
@XmlAttribute(name = "dropForeignKeyIndex")
@@ -504,6 +509,46 @@ public class AlterColumn {
this.foreignKeyIndex = value;
}
/**
* Gets the value of the foreignKeyOnDelete property.
*
* @return possible object is
* {@link String }
*/
public String getForeignKeyOnDelete() {
return foreignKeyOnDelete;
}
/**
* Sets the value of the foreignKeyOnDelete property.
*
* @param value allowed object is
* {@link String }
*/
public void setForeignKeyOnDelete(String value) {
this.foreignKeyOnDelete = value;
}
/**
* Gets the value of the foreignKeyOnUpdate property.
*
* @return possible object is
* {@link String }
*/
public String getForeignKeyOnUpdate() {
return foreignKeyOnUpdate;
}
/**
* Sets the value of the foreignKeyOnUpdate property.
*
* @param value allowed object is
* {@link String }
*/
public void setForeignKeyOnUpdate(String value) {
this.foreignKeyOnUpdate = value;
}
/**
* Gets the value of the dropForeignKey property.
*
@@ -1,14 +1,13 @@
package io.ebeaninternal.dbmigration.migration;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
@@ -34,6 +33,8 @@ import javax.xml.bind.annotation.XmlType;
* &lt;attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="comment" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
@@ -80,6 +81,10 @@ public class Column {
protected String foreignKeyName;
@XmlAttribute(name = "foreignKeyIndex")
protected String foreignKeyIndex;
@XmlAttribute(name = "foreignKeyOnDelete")
protected String foreignKeyOnDelete;
@XmlAttribute(name = "foreignKeyOnUpdate")
protected String foreignKeyOnUpdate;
@XmlAttribute(name = "comment")
protected String comment;
@@ -378,6 +383,46 @@ public class Column {
this.foreignKeyIndex = value;
}
/**
* Gets the value of the foreignOnDelete property.
*
* @return possible object is
* {@link String }
*/
public String getForeignKeyOnDelete() {
return foreignKeyOnDelete;
}
/**
* Sets the value of the foreignKeyOnDelete property.
*
* @param value allowed object is
* {@link String }
*/
public void setForeignKeyOnDelete(String value) {
this.foreignKeyOnDelete = value;
}
/**
* Gets the value of the foreignOnUpdate property.
*
* @return possible object is
* {@link String }
*/
public String getForeignKeyOnUpdate() {
return foreignKeyOnUpdate;
}
/**
* Sets the value of the foreignKeyOnUpdate property.
*
* @param value allowed object is
* {@link String }
*/
public void setForeignKeyOnUpdate(String value) {
this.foreignKeyOnUpdate = value;
}
/**
* Gets the value of the comment property.
*
@@ -21,6 +21,8 @@ import javax.xml.bind.annotation.XmlType;
* &lt;attribute name="refColumnNames" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="refTableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="indexName" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="onDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="onUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
@@ -41,7 +43,10 @@ public class ForeignKey {
protected String refTableName;
@XmlAttribute(name = "indexName")
protected String indexName;
@XmlAttribute(name = "onDelete")
protected String onDelete;
@XmlAttribute(name = "onUpdate")
protected String onUpdate;
/**
* Gets the value of the name property.
*
@@ -142,4 +147,44 @@ public class ForeignKey {
this.indexName = value;
}
/**
* Gets the value of the onDelete property.
*
* @return possible object is
* {@link String }
*/
public String getOnDelete() {
return onDelete;
}
/**
* Sets the value of the onDelete property.
*
* @param value allowed object is
* {@link String }
*/
public void setOnDelete(String value) {
this.onDelete = value;
}
/**
* Gets the value of the onUpdate property.
*
* @return possible object is
* {@link String }
*/
public String getOnUpdate() {
return onUpdate;
}
/**
* Sets the value of the onUpdate property.
*
* @param value allowed object is
* {@link String }
*/
public void setOnUpdate(String value) {
this.onUpdate = value;
}
}
@@ -1,13 +1,14 @@
package io.ebeaninternal.dbmigration.model;
import java.util.List;
import io.ebean.annotation.ConstraintMode;
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
import io.ebeaninternal.dbmigration.migration.AlterColumn;
import io.ebeaninternal.dbmigration.migration.Column;
import io.ebeaninternal.dbmigration.migration.DdlScript;
import io.ebeaninternal.server.deploy.DbMigrationInfo;
import java.util.List;
/**
* A column in the logical model.
*/
@@ -21,6 +22,8 @@ public class MColumn {
private String references;
private String foreignKeyName;
private String foreignKeyIndex;
private ConstraintMode fkeyOnDelete;
private ConstraintMode fkeyOnUpdate;
private String comment;
private boolean historyExclude;
@@ -55,6 +58,8 @@ public class MColumn {
this.references = column.getReferences();
this.foreignKeyName = column.getForeignKeyName();
this.foreignKeyIndex = column.getForeignKeyIndex();
this.fkeyOnDelete = fkeyMode(column.getForeignKeyOnDelete());
this.fkeyOnUpdate = fkeyMode(column.getForeignKeyOnUpdate());
this.notnull = Boolean.TRUE.equals(column.isNotnull());
this.primaryKey = Boolean.TRUE.equals(column.isPrimaryKey());
this.identity = Boolean.TRUE.equals(column.isIdentity());
@@ -63,6 +68,10 @@ public class MColumn {
this.historyExclude = Boolean.TRUE.equals(column.isHistoryExclude());
}
private ConstraintMode fkeyMode(String mode) {
return (mode == null) ? null : ConstraintMode.valueOf(mode);
}
public MColumn(String name, String type) {
this.name = name;
this.type = type;
@@ -89,6 +98,8 @@ public class MColumn {
copy.comment = comment;
copy.foreignKeyName = foreignKeyName;
copy.foreignKeyIndex = foreignKeyIndex;
copy.fkeyOnUpdate = fkeyOnUpdate;
copy.fkeyOnDelete = fkeyOnDelete;
copy.historyExclude = historyExclude;
copy.notnull = notnull;
copy.primaryKey = primaryKey;
@@ -154,6 +165,11 @@ public class MColumn {
this.foreignKeyIndex = foreignKeyIndex;
}
public void setForeignKeyModes(ConstraintMode onDelete, ConstraintMode onUpdate) {
this.fkeyOnDelete = onDelete;
this.fkeyOnUpdate = onUpdate;
}
public String getDefaultValue() {
return defaultValue;
}
@@ -196,7 +212,7 @@ public class MColumn {
/**
* Set unique specifically for OneToOne mapping.
* We need special DDL for this case for MsSqlServer.
* We need special DDL for this case for SqlServer.
*/
public void setUniqueOneToOne(String uniqueOneToOne) {
this.uniqueOneToOne = uniqueOneToOne;
@@ -260,6 +276,8 @@ public class MColumn {
c.setReferences(references);
c.setForeignKeyName(foreignKeyName);
c.setForeignKeyIndex(foreignKeyIndex);
c.setForeignKeyOnDelete(fkeyModeOf(fkeyOnDelete));
c.setForeignKeyOnUpdate(fkeyModeOf(fkeyOnUpdate));
c.setDefaultValue(defaultValue);
c.setComment(comment);
c.setUnique(unique);
@@ -286,6 +304,10 @@ public class MColumn {
return c;
}
private String fkeyModeOf(ConstraintMode mode) {
return (mode == null) ? null : mode.name();
}
protected static boolean different(String val1, String val2) {
return (val1 == null) ? val2 != null : !val1.equals(val2);
}
@@ -11,6 +11,7 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import io.ebeaninternal.server.deploy.IndexDefinition;
import io.ebeaninternal.server.deploy.InheritInfo;
import io.ebeaninternal.server.deploy.PropertyForeignKey;
import io.ebeaninternal.server.deploy.TableJoin;
import io.ebeaninternal.server.deploy.TableJoinColumn;
import io.ebeaninternal.server.deploy.id.ImportedId;
@@ -156,6 +157,8 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
List<MColumn> modelColumns = new ArrayList<>(columns.length);
PropertyForeignKey foreignKey = p.getForeignKey();
MCompoundForeignKey compoundKey = null;
if (columns.length > 1) {
// compound foreign key
@@ -180,15 +183,22 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
col.setDbMigrationInfos(p.getDbMigrationInfos());
col.setDefaultValue(p.getDbColumnDefault());
if (columns.length == 1) {
// single references column (put it on the column)
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
if (refTable == null) {
// odd case where an EmbeddedId only has 1 property
refTable = p.getTargetDescriptor().getBaseTable();
if (p.hasForeignKey()) {
// single references column (put it on the column)
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
if (refTable == null) {
// odd case where an EmbeddedId only has 1 property
refTable = p.getTargetDescriptor().getBaseTable();
}
col.setReferences(refTable + "." + refColumn);
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
if (p.hasForeignKeyIndex()) {
col.setForeignKeyIndex(determineForeignKeyIndexName(col.getName()));
}
if (foreignKey != null) {
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
}
}
col.setReferences(refTable + "." + refColumn);
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
col.setForeignKeyIndex(determineForeignKeyIndexName(col.getName()));
} else {
compoundKey.addColumnPair(dbCol, refColumn);
}
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy;
import io.ebean.BackgroundExecutor;
import io.ebean.Model;
import io.ebean.RawSqlBuilder;
import io.ebean.annotation.ConstraintMode;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean;
import io.ebean.config.EncryptKey;
@@ -1156,7 +1157,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
// get the mappedBy property
DeployBeanProperty mappedProp = targetDesc.getBeanProperty(mappedBy);
if (mappedProp == null) {
String m = "Error on " + prop.getFullBeanName();
m += " Can not find mappedBy property [" + mappedBy + "] ";
m += "in [" + targetDesc + "]";
@@ -1179,6 +1179,19 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
otherTableJoin.copyTo(tableJoin, true, tableJoin.getTable());
}
PropertyForeignKey foreignKey = mappedAssocOne.getForeignKey();
if (foreignKey != null) {
ConstraintMode onDelete = foreignKey.getOnDelete();
switch (onDelete) {
case SET_DEFAULT:
case SET_NULL:
case CASCADE: {
// turn off cascade delete when we are using the foreign
// key constraint to cascade the delete or set null
prop.getCascadeInfo().setDelete(false);
}
}
}
}
/**
@@ -41,6 +41,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
private final boolean primaryKeyExport;
private final PropertyForeignKey foreignKey;
private AssocOneHelp localHelp;
protected final BeanProperty[] embeddedProps;
@@ -69,6 +71,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
super(descriptor, deploy);
foreignKey = deploy.getForeignKey();
primaryKeyExport = deploy.isPrimaryKeyExport();
importedPrimaryKey = deploy.isImportedPrimaryKey();
oneToOne = deploy.isOneToOne();
@@ -309,6 +312,18 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
}
public PropertyForeignKey getForeignKey() {
return foreignKey;
}
public boolean hasForeignKey() {
return foreignKey == null || !foreignKey.isNoConstraint();
}
public boolean hasForeignKeyIndex() {
return foreignKey == null || !foreignKey.isNoIndex();
}
/**
* Return true if this a OneToOne property. Otherwise assumed ManyToOne.
*/
@@ -0,0 +1,35 @@
package io.ebeaninternal.server.deploy;
import io.ebean.annotation.ConstraintMode;
import io.ebean.annotation.DbForeignKey;
public class PropertyForeignKey {
private final boolean noIndex;
private final boolean noConstraint;
private final ConstraintMode onDelete;
private final ConstraintMode onUpdate;
public PropertyForeignKey(DbForeignKey dbForeignKey) {
this.noIndex = dbForeignKey.noIndex();
this.noConstraint = dbForeignKey.noConstraint();
this.onDelete = dbForeignKey.onDelete();
this.onUpdate = dbForeignKey.onUpdate();
}
public boolean isNoIndex() {
return noIndex;
}
public boolean isNoConstraint() {
return noConstraint;
}
public ConstraintMode getOnDelete() {
return onDelete;
}
public ConstraintMode getOnUpdate() {
return onUpdate;
}
}
@@ -1,5 +1,7 @@
package io.ebeaninternal.server.deploy.meta;
import io.ebeaninternal.server.deploy.PropertyForeignKey;
import javax.persistence.CascadeType;
/**
@@ -21,6 +23,8 @@ public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
private String columnPrefix;
private PropertyForeignKey foreignKey;
/**
* Create the property.
*/
@@ -148,4 +152,12 @@ public class DeployBeanPropertyAssocOne<T> extends DeployBeanPropertyAssoc<T> {
cascadeInfo.setType(CascadeType.ALL);
}
}
public void setForeignKey(PropertyForeignKey foreignKey) {
this.foreignKey = foreignKey;
}
public PropertyForeignKey getForeignKey() {
return foreignKey;
}
}
@@ -1,10 +1,12 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.annotation.DbForeignKey;
import io.ebean.annotation.FetchPreference;
import io.ebean.annotation.Where;
import io.ebean.config.NamingConvention;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.BeanTable;
import io.ebeaninternal.server.deploy.PropertyForeignKey;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
@@ -89,6 +91,11 @@ public class AnnotationAssocOnes extends AnnotationParser {
prop.setNullable(false);
}
DbForeignKey dbForeignKey = get(prop, DbForeignKey.class);
if (dbForeignKey != null){
prop.setForeignKey(new PropertyForeignKey(dbForeignKey));
}
Where where = get(prop, Where.class);
if (where != null) {
// not expecting this to be used on assoc one properties