#101 - SQL SERVER - drop.sql does not disable referential integrity

This commit is contained in:
rbygrave
2014-12-17 00:52:31 +13:00
parent 56fd6b90be
commit 965de6e84d
5 changed files with 160 additions and 75 deletions
@@ -7,30 +7,35 @@ import com.avaje.ebean.config.TableName;
*/
public class DbDdlSyntax {
private boolean renderIndexForFkey = true;
protected boolean renderIndexForFkey = true;
private boolean inlinePrimaryKeyConstraint = false;
protected boolean inlinePrimaryKeyConstraint = false;
private boolean addOneToOneUniqueContraint = true;
protected boolean addOneToOneUniqueContraint = true;
private int maxConstraintNameLength = 32;
protected int maxConstraintNameLength = 32;
private int columnNameWidth = 25;
protected int columnNameWidth = 25;
private String dropTableCascade;
private String dropIfExists;
/**
* Flag set when we want to disable constraints on each table (rather than globally).
*/
protected boolean dropKeyConstraints;
private String newLine = "\n";
protected String dropTableCascade;
protected String dropIfExists;
private String identity = "auto_increment";
private String identitySuffix = "";
protected String newLine = "\n";
private String pkPrefix = "pk_";
protected String identity = "auto_increment";
protected String identitySuffix = "";
private String disableReferentialIntegrity;
private String enableReferentialIntegrity;
protected String pkPrefix = "pk_";
private String foreignKeySuffix;
protected String disableReferentialIntegrity;
protected String enableReferentialIntegrity;
protected String foreignKeySuffix;
/**
* Return the primary key name for a given bean descriptor.
@@ -158,6 +163,20 @@ public class DbDdlSyntax {
this.enableReferentialIntegrity = enableReferentialIntegrity;
}
/**
* Return true to is constraints are disabled on each table.
*/
public boolean isDropKeyConstraints() {
return dropKeyConstraints;
}
/**
* Return some DDL to disable constraints on the given table.
*/
public String dropKeyConstraintPrefix(String tableName, String fkName) {
return null;
}
/**
* Return true if indexes should be created for the foreign keys.
*/
@@ -188,6 +207,13 @@ public class DbDdlSyntax {
this.dropIfExists = dropIfExists;
}
/**
* Return prefix text that goes before drop table.
*/
public String dropTablePrefix(String tableName) {
return "";
}
/**
* Return the cascade option for the drop table command.
*/
@@ -17,8 +17,12 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
public MsSqlServer2005Platform() {
super();
this.name = "mssqlserver2005";
// effectively disable persistBatchOnCascade mode for SQL Server
// due to lack of support for getGeneratedKeys in batch mode
this.disallowBatchOnCascade = true;
this.idInExpandedForm = true;
this.sqlLimiter = new MsSqlServer2005SqlLimiter();
this.dbDdlSyntax.setIdentity("identity(1,1)");
this.dbDdlSyntax = new MsDdlSyntax();
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
@@ -28,6 +32,7 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
dbTypeMap.put(Types.BOOLEAN, new DbType("bit default 0"));
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
dbTypeMap.put(Types.BIGINT, new DbType("numeric", 19));
dbTypeMap.put(Types.REAL, new DbType("float(16)"));
dbTypeMap.put(Types.DOUBLE, new DbType("float(32)"));
@@ -45,4 +50,30 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
}
/**
* MS SQL Server specific DDL Syntax.
*/
public class MsDdlSyntax extends DbDdlSyntax {
MsDdlSyntax() {
this.identity = "identity(1,1)";
this.dropKeyConstraints = true;
}
/**
* Return some DDL to disable constraints on the given table.
*/
public String dropKeyConstraintPrefix(String tableName, String fkName) {
return "IF OBJECT_ID('"+fkName+"', 'F') IS NOT NULL";
}
/**
* Return prefix text that goes before drop table.
*/
public String dropTablePrefix(String tableName) {
return "IF OBJECT_ID('"+tableName+"', 'U') IS NOT NULL ";
}
}
}
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.ddl;
import com.avaje.ebean.config.dbplatform.DbDdlSyntax;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
@@ -16,23 +17,23 @@ public class AddForeignKeysVisitor extends AbstractBeanVisitor {
final FkeyPropertyVisitor pv;
public AddForeignKeysVisitor(DdlGenContext ctx) {
public AddForeignKeysVisitor(boolean addMode, DdlGenContext ctx) {
this.ctx = ctx;
this.pv = new FkeyPropertyVisitor(this, ctx);
this.pv = new FkeyPropertyVisitor(addMode, this, ctx);
}
public boolean visitBean(BeanDescriptor<?> descriptor) {
if (!descriptor.isInheritanceRoot()){
// ignore/skip if not a top level BeanDescriptor
return false;
}
return true;
}
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
visitInheritanceProperties(descriptor, pv);
public boolean visitBean(BeanDescriptor<?> descriptor) {
if (!descriptor.isInheritanceRoot()) {
// ignore/skip if not a top level BeanDescriptor
return false;
}
return true;
}
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
visitInheritanceProperties(descriptor, pv);
}
public void visitBegin() {
}
@@ -48,11 +49,17 @@ public class AddForeignKeysVisitor extends AbstractBeanVisitor {
public static class FkeyPropertyVisitor extends BaseTablePropertyVisitor {
/**
* Set to false when generating drop foreign key statements.
*/
final boolean addMode;
final DdlGenContext ctx;
final AddForeignKeysVisitor parent;
public FkeyPropertyVisitor(AddForeignKeysVisitor parent, DdlGenContext ctx) {
public FkeyPropertyVisitor(boolean addMode, AddForeignKeysVisitor parent, DdlGenContext ctx) {
this.addMode = addMode;
this.parent = parent;
this.ctx = ctx;
}
@@ -69,51 +76,59 @@ public class AddForeignKeysVisitor extends AbstractBeanVisitor {
// Alter table o_address add Foreign Key (country_code) references o_country (code) on delete restrict on update restrict;
String baseTable = p.getBeanDescriptor().getBaseTable();
TableJoin tableJoin = p.getTableJoin();
TableJoinColumn[] columns = tableJoin.columns();
String tableName = p.getBeanDescriptor().getBaseTable();
String fkName = ctx.getDdlSyntax().getForeignKeyName(tableName, p.getName(), ctx.incrementFkCount());
ctx.write("alter table ").write(baseTable).write(" add ");
DbDdlSyntax ddlSyntax = ctx.getDdlSyntax();
String fkName = ddlSyntax.getForeignKeyName(tableName, p.getName(), ctx.incrementFkCount());
if (!addMode) {
// look to generate drop foreign key statement
String dropKeyConstraintPrefix = ddlSyntax.dropKeyConstraintPrefix(tableName, fkName);
if (dropKeyConstraintPrefix != null && !dropKeyConstraintPrefix.isEmpty()) {
ctx.write(dropKeyConstraintPrefix).write(" ");
}
}
ctx.write("alter table ").write(baseTable).write(addOrDrop());
if (fkName != null) {
ctx.write("constraint ").write(fkName).write(" ");
}
ctx.write("foreign key (");
for (int i = 0; i < columns.length; i++) {
if (i > 0){
ctx.write(",");
}
ctx.write(columns[i].getLocalDbColumn());
}
ctx.write(")");
if (addMode) {
ctx.write("foreign key (");
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
ctx.write(",");
}
ctx.write(columns[i].getLocalDbColumn());
}
ctx.write(")");
ctx.write(" references ");
ctx.write(tableJoin.getTable());
ctx.write(" (");
for (int i = 0; i < columns.length; i++) {
if (i > 0){
ctx.write(",");
}
ctx.write(columns[i].getForeignDbColumn());
}
ctx.write(")");
ctx.write(" references ");
ctx.write(tableJoin.getTable());
ctx.write(" (");
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
ctx.write(",");
}
ctx.write(columns[i].getForeignDbColumn());
}
ctx.write(")");
String fkeySuffix = ctx.getDdlSyntax().getForeignKeySuffix();
if (fkeySuffix != null){
ctx.write(" ").write(fkeySuffix);
}
String fkeySuffix = ctx.getDdlSyntax().getForeignKeySuffix();
if (fkeySuffix != null) {
ctx.write(" ").write(fkeySuffix);
}
}
ctx.write(";").writeNewLine();
if (ctx.getDdlSyntax().isRenderIndexForFkey()){
if (addMode && ddlSyntax.isRenderIndexForFkey()){
//create index idx_fk_o_address_ctry on o_address(country_code);
ctx.write("create index ");
String idxName = ctx.getDdlSyntax().getIndexName(tableName, p.getName(), ctx.incrementIxCount());
String idxName = ddlSyntax.getIndexName(tableName, p.getName(), ctx.incrementIxCount());
if (idxName != null){
ctx.write(idxName);
}
@@ -129,21 +144,27 @@ public class AddForeignKeysVisitor extends AbstractBeanVisitor {
}
}
@Override
public void visitScalar(BeanProperty p) {
// not interested
}
/**
* Return 'add' or 'drop' of foreign key.
*/
protected String addOrDrop() {
return addMode ? " add " : " drop " ;
}
@Override
public void visitCompound(BeanPropertyCompound p) {
// not interested
}
@Override
public void visitScalar(BeanProperty p) {
// not interested
}
@Override
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
// not interested
}
}
@Override
public void visitCompound(BeanPropertyCompound p) {
// not interested
}
@Override
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
// not interested
}
}
}
@@ -126,6 +126,13 @@ public class DdlGenerator implements SpiEbeanPlugin {
DdlGenContext ctx = createContext();
if (ctx.getDdlSyntax().isDropKeyConstraints()) {
// generate drop foreign key constraint statements (sql server joy)
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(false, ctx);
VisitorUtil.visit(server, fkeys);
ctx.writeNewLine();
}
DropTableVisitor drop = new DropTableVisitor(ctx);
VisitorUtil.visit(server, drop);
@@ -146,7 +153,7 @@ public class DdlGenerator implements SpiEbeanPlugin {
CreateSequenceVisitor createSequence = new CreateSequenceVisitor(ctx);
VisitorUtil.visit(server, createSequence);
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(ctx);
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(true, ctx);
VisitorUtil.visit(server, fkeys);
CreateIndexVisitor indexes = new CreateIndexVisitor(ctx);
@@ -275,7 +282,6 @@ public class DdlGenerator implements SpiEbeanPlugin {
} catch (Exception e) {
if (expectErrors) {
logger.info(" ... ignoring error executing " + getSummary(stmt) + " error: " + e.getMessage());
e.printStackTrace();
} else {
String msg = "Error executing stmt[" + stmt + "] error[" + e.getMessage() + "]";
throw new RuntimeException(msg, e);
@@ -24,6 +24,7 @@ public class DropTableVisitor implements BeanVisitor {
}
protected void writeDropTable(String tableName){
ctx.write(ddlSyntax.dropTablePrefix(tableName));
ctx.write("drop table ");
if (ddlSyntax.getDropIfExists() != null){
ctx.write(ddlSyntax.getDropIfExists()).write(" ");