mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#323 - DDL Generation support for foreign key cascade options
This commit is contained in:
+17
-67
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+48
-15
@@ -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();
|
||||
|
||||
+100
@@ -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;
|
||||
* <attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="dropForeignKey" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="dropForeignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </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;
|
||||
* <attribute name="references" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyIndex" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="foreignKeyOnUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="comment" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </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;
|
||||
* <attribute name="refColumnNames" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="refTableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="indexName" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onDelete" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* <attribute name="onUpdate" type="{http://www.w3.org/2001/XMLSchema}string" />
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </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);
|
||||
}
|
||||
|
||||
+18
-8
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user