From dcde54fca42f4fd09b2ce2f0d6022092d4b31d8b Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Mon, 21 Mar 2016 11:06:52 +1300 Subject: [PATCH] #100 - SQLITE (365) : ADD CONSTRAINT DDL SQLite Incompatibility --- .../ddlgeneration/platform/BaseTableDdl.java | 45 ++++++++++++++++++- .../ddlgeneration/platform/PlatformDdl.java | 27 +++++++++++ .../ddlgeneration/platform/SQLiteDdl.java | 1 + 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java index 065b8a4d5..1914b333b 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -123,6 +123,9 @@ public class BaseTableDdl implements TableDdl { // defined on the columns writePrimaryKeyConstraint(apply, createTable.getPkName(), toColumnNames(pk)); } + if (platformDdl.isInlineForeignKeys()) { + writeInlineForeignKeys(writer, createTable); + } apply.newLine().append(")"); addTableCommentInline(apply, createTable); @@ -151,8 +154,9 @@ public class BaseTableDdl implements TableDdl { apply.end(); writer.dropAll().end(); - writeAddForeignKeys(writer, createTable); - + if (!platformDdl.isInlineForeignKeys()) { + writeAddForeignKeys(writer, createTable); + } } /** @@ -235,6 +239,43 @@ public class BaseTableDdl implements TableDdl { platformDdl.createWithHistory(writer, table); } + protected void writeInlineForeignKeys(DdlWrite write, CreateTable createTable) throws IOException { + + for (Column column : createTable.getColumn()) { + String references = column.getReferences(); + if (hasValue(references)) { + writeInlineForeignKey(write, column); + } + } + writeInlineCompoundForeignKeys(write, createTable); + } + + 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}); + write.apply().append(",").newLine().append(" ").append(fkConstraint); + } + + protected void writeInlineCompoundForeignKeys(DdlWrite write, CreateTable createTable) throws IOException { + + List 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); + write.apply().append(",").newLine().append(" ").append(fkConstraint); + } + } + protected void writeAddForeignKeys(DdlWrite write, CreateTable createTable) throws IOException { String tableName = createTable.getName(); diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java index 37d1ea7c5..e11017105 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -85,6 +85,11 @@ public class PlatformDdl { protected DbConstraintNaming naming; + /** + * Generally not desired as then they are not named (used with SQLite). + */ + protected boolean inlineForeignKeys; + public PlatformDdl(DbTypeMap platformTypes, DbIdentity dbIdentity) { this.dbIdentity = dbIdentity; this.typeConverter = new PlatformTypeConverter(platformTypes); @@ -128,6 +133,14 @@ public class PlatformDdl { return inlineComments; } + /** + * Return true if foreign key reference constraints need to inlined with create table. + * Ideally we don't do this as then the constraints are not named. Do this for SQLite. + */ + public boolean isInlineForeignKeys() { + return inlineForeignKeys; + } + /** * Write all the table columns converting to platform types as necessary. */ @@ -255,6 +268,20 @@ public class PlatformDdl { return buffer.toString(); } + /** + * Return the foreign key constraint when used inline with create table. + */ + public String tableInlineForeignKey(String[] columns, String refTable, String[] refColumns) { + + StringBuilder buffer = new StringBuilder(90); + buffer.append("foreign key"); + appendColumns(columns, buffer); + buffer.append(" references ").append(lowerTableName(refTable)); + appendColumns(refColumns, buffer); + appendWithSpace(foreignKeyRestrict, buffer); + return buffer.toString(); + } + /** * Add foreign key. */ diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/SQLiteDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/SQLiteDdl.java index d40f43707..7b0f9e2a8 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/SQLiteDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/SQLiteDdl.java @@ -14,6 +14,7 @@ public class SQLiteDdl extends PlatformDdl { public SQLiteDdl(DbTypeMap platformTypes, DbIdentity dbIdentity) { super(platformTypes, dbIdentity); this.identitySuffix = ""; + this.inlineForeignKeys = true; } @Override