From fe9500e6d01b7ae6508ddfd325c10fee288d7a7c Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Sat, 20 May 2017 23:40:02 +1200 Subject: [PATCH] #1011 - Create valid migration scripts for non-Postgres databases and @DbArray columns. Merge branch 'test/dbarray-create-migration' of https://github.com/FOCONIS/ebean into FOCONIS-test/dbarray-create-migration commit 3a8f32b173753f91504220ebc9808802ada52534 Author: Michael Benz Date: Wed Apr 19 18:16:51 2017 +0200 adding dbmigration ddlgeneration test for Ebean @DbArray extension. --- .../ddlgeneration/platform/H2Ddl.java | 4 ++ .../ddlgeneration/platform/PlatformDdl.java | 16 +++++ .../ddlgeneration/platform/PostgresDdl.java | 11 +++ .../server/deploy/parse/DeployUtil.java | 16 +++-- .../server/type/ScalarTypeArrayListH2.java | 5 -- .../server/type/ScalarTypeArraySetH2.java | 5 -- .../server/type/ScalarTypeJsonCollection.java | 19 +++++- .../ddlgeneration/BaseDdlHandlerTest.java | 68 ++++++++++++++++++- .../dbmigration/ddlgeneration/Helper.java | 16 +++++ .../platform/PlatformDdl_AlterColumnTest.java | 30 +++++++- .../resources/container/test-alter-table.xml | 18 ++++- 11 files changed, 184 insertions(+), 24 deletions(-) diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/H2Ddl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/H2Ddl.java index 4e5e0e4bbb..81d534e44b 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/H2Ddl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/H2Ddl.java @@ -12,4 +12,8 @@ public H2Ddl(DatabasePlatform platform) { this.historyDdl = new H2HistoryDdl(); } + @Override + protected String convertArrayType(String logicalArrayType) { + return "array"; + } } diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java index 7328bfd54f..483cb465c6 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -99,6 +99,8 @@ public class PlatformDdl { protected final DbDefaultValue dbDefaultValue; + protected String fallbackArrayType = "varchar(1000)"; + public PlatformDdl(DatabasePlatform platform) { this.platform = platform; this.dbIdentity = platform.getDbIdentity(); @@ -215,10 +217,24 @@ public String alterTableDropForeignKey(String tableName, String fkName) { * Convert the standard type to the platform specific type. */ public String convert(String type, boolean identity) { + if (type.contains("[]")) { + return convertArrayType(type); + } String platformType = typeConverter.convert(type); return identity ? asIdentityColumn(platformType) : platformType; } + /** + * Convert the logical array type to a db platform specific type to support the array data. + */ + protected String convertArrayType(String logicalArrayType) { + if (logicalArrayType.endsWith("]")) { + return fallbackArrayType; + } + int colonPos = logicalArrayType.lastIndexOf(']'); + return "varchar" + logicalArrayType.substring(colonPos + 1); + } + /** * Add history support to this table using the platform specific mechanism. */ diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PostgresDdl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PostgresDdl.java index 58415d4fc1..1bbe8b4492 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PostgresDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PostgresDdl.java @@ -16,6 +16,17 @@ public PostgresDdl(DatabasePlatform platform) { this.columnSetNull = "drop not null"; } + @Override + protected String convertArrayType(String logicalArrayType) { + int colonPos = logicalArrayType.lastIndexOf(']'); + if (colonPos == -1) { + return logicalArrayType; + } else { + // trim of the fallback varchar length + return logicalArrayType.substring(0, colonPos + 1); + } + } + /** * Map bigint, integer and smallint into their equivalent serial types. */ diff --git a/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java b/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java index 9d250b4bbc..a7ad482c06 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java +++ b/src/main/java/io/ebeaninternal/server/deploy/parse/DeployUtil.java @@ -245,13 +245,15 @@ public void setDbArray(DeployBeanProperty prop, DbArray dbArray) { prop.setDbType(dbType); prop.setScalarType(scalarType); if (scalarType instanceof ScalarTypeArray) { - prop.setDbColumnDefn(((ScalarTypeArray) scalarType).getDbColumnDefn()); - } - if (dbType == Types.VARCHAR) { - // determine the db column size - int dbLength = dbArray.length(); - int columnLength = (dbLength > 0) ? dbLength : DEFAULT_ARRAY_VARCHAR_LENGTH; - prop.setDbLength(columnLength); + String columnDefn = ((ScalarTypeArray) scalarType).getDbColumnDefn(); + if (dbArray.length() > 0) { + // fallback varchar column length when ARRAY not support by DB + columnDefn += "(" + dbArray.length() + ")"; + } + prop.setDbLength(dbArray.length()); + prop.setDbColumnDefn(columnDefn); + } else { + throw new RuntimeException("Not mapped to ScalarTypeArray? " + scalarType.getClass()); } } diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayListH2.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayListH2.java index daf2bab064..11f1ab1750 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayListH2.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeArrayListH2.java @@ -52,11 +52,6 @@ private ScalarTypeArrayListH2(String arrayType, DocPropertyType docPropertyType, super(arrayType, docPropertyType, converter); } - @Override - public String getDbColumnDefn() { - return "array"; - } - @Override public void bind(DataBind bind, List value) throws SQLException { if (value == null) { diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySetH2.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySetH2.java index 279d57864c..aa8a2a23ad 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySetH2.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeArraySetH2.java @@ -52,11 +52,6 @@ private ScalarTypeArraySetH2(String arrayType, DocPropertyType docPropertyType, super(arrayType, docPropertyType, converter); } - @Override - public String getDbColumnDefn() { - return "array"; - } - @Override public void bind(DataBind bind, Set value) throws SQLException { if (value == null) { diff --git a/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonCollection.java b/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonCollection.java index 929ebce0ce..534ce2d489 100644 --- a/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonCollection.java +++ b/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonCollection.java @@ -6,7 +6,7 @@ import java.io.DataOutput; import java.io.IOException; -abstract class ScalarTypeJsonCollection extends ScalarTypeBase { +abstract class ScalarTypeJsonCollection extends ScalarTypeBase implements ScalarTypeArray { protected DocPropertyType docPropertyType; @@ -15,6 +15,23 @@ public ScalarTypeJsonCollection(Class type, int dbType, DocPropertyType docPr this.docPropertyType = docPropertyType; } + /** + * Return the logical db column definition based on the element document type. + */ + @Override + public String getDbColumnDefn() { + switch (docPropertyType) { + case SHORT: + case INTEGER: + case LONG: + return "integer[]"; + case DOUBLE: + case FLOAT: + return "decimal[]"; + } + return "varchar[]"; + } + /** * Consider as a mutable type. Use the isDirty() method to check for dirty state. */ diff --git a/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java b/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java index 0e5fe1ca8d..5bb490a4e8 100644 --- a/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java +++ b/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java @@ -5,6 +5,7 @@ import io.ebean.config.ServerConfig; import io.ebean.config.dbplatform.h2.H2Platform; import io.ebean.config.dbplatform.postgres.PostgresPlatform; +import io.ebean.config.dbplatform.sqlserver.SqlServerPlatform; import io.ebean.dbmigration.migration.ChangeSet; import io.ebean.dbmigration.model.CurrentModel; import io.ebeaninternal.api.SpiEbeanServer; @@ -26,17 +27,78 @@ private DdlHandler postgresHandler() { return new PostgresPlatform().createDdlHandler(serverConfig); } + private DdlHandler sqlserverHandler() { + return new SqlServerPlatform().createDdlHandler(serverConfig); + } + @Test public void addColumn_nullable_noConstraint() throws Exception { DdlWrite write = new DdlWrite(); + h2Handler().generate(write, Helper.getAddColumn()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column added_to_foo varchar(20);\n\n"); - DdlHandler handler = h2Handler(); - handler.generate(write, Helper.getAddColumn()); - + write = new DdlWrite(); + sqlserverHandler().generate(write, Helper.getAddColumn()); assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column added_to_foo varchar(20);\n\n"); } + /** + * Test the functionality of the Ebean {@literal @}DbArray extension during DDL generation. + */ + @Test + public void addColumn_dbarray() throws Exception { + + DdlWrite write = new DdlWrite(); + + DdlHandler postgresHandler = postgresHandler(); + postgresHandler.generate(write, Helper.getAlterTableAddDbArrayColumn()); + + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_added_to_foo varchar[];\n\n"); + + write = new DdlWrite(); + + DdlHandler sqlserverHandler = sqlserverHandler(); + sqlserverHandler.generate(write, Helper.getAlterTableAddDbArrayColumn()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_added_to_foo varchar(1000);\n\n"); + } + + @Test + public void addColumn_dbarray_withLength() throws Exception { + + DdlWrite write = new DdlWrite(); + + postgresHandler().generate(write, Helper.getAlterTableAddDbArrayColumnWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety varchar[];\n\n"); + + write = new DdlWrite(); + h2Handler().generate(write, Helper.getAlterTableAddDbArrayColumnWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety array;\n\n"); + + write = new DdlWrite(); + sqlserverHandler().generate(write, Helper.getAlterTableAddDbArrayColumnWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_ninety varchar(90);\n\n"); + } + + @Test + public void addColumn_dbarray_integer_withLength() throws Exception { + + DdlWrite write = new DdlWrite(); + postgresHandler().generate(write, Helper.getAlterTableAddDbArrayColumnIntegerWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer integer[];\n\n"); + + write = new DdlWrite(); + h2Handler().generate(write, Helper.getAlterTableAddDbArrayColumnIntegerWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer array;\n\n"); + + write = new DdlWrite(); + sqlserverHandler().generate(write, Helper.getAlterTableAddDbArrayColumnIntegerWithLength()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer varchar(90);\n\n"); + + write = new DdlWrite(); + sqlserverHandler().generate(write, Helper.getAlterTableAddDbArrayColumnInteger()); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column dbarray_integer varchar(1000);\n\n"); + } @Test public void addColumn_withForeignKey() throws Exception { diff --git a/src/test/java/io/ebean/dbmigration/ddlgeneration/Helper.java b/src/test/java/io/ebean/dbmigration/ddlgeneration/Helper.java index 9918bce8e3..decb0fc2a6 100644 --- a/src/test/java/io/ebean/dbmigration/ddlgeneration/Helper.java +++ b/src/test/java/io/ebean/dbmigration/ddlgeneration/Helper.java @@ -55,6 +55,22 @@ public static AddColumn getAlterTableAddColumn() { return (AddColumn) alterTableChangeSetChildren.get(0); } + public static AddColumn getAlterTableAddDbArrayColumn() { + return (AddColumn) alterTableChangeSetChildren.get(1); + } + + public static AddColumn getAlterTableAddDbArrayColumnWithLength() { + return (AddColumn) alterTableChangeSetChildren.get(2); + } + + public static AddColumn getAlterTableAddDbArrayColumnIntegerWithLength() { + return (AddColumn) alterTableChangeSetChildren.get(3); + } + + public static AddColumn getAlterTableAddDbArrayColumnInteger() { + return (AddColumn) alterTableChangeSetChildren.get(4); + } + public static DropColumn getDropColumn() { return (DropColumn) changeSetChildren.get(2); } diff --git a/src/test/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java b/src/test/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java index 66d6e72b3b..17c2eea75e 100644 --- a/src/test/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java +++ b/src/test/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl_AlterColumnTest.java @@ -8,8 +8,10 @@ import io.ebean.dbmigration.migration.AlterColumn; import org.junit.Test; -import static org.junit.Assert.*; - +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; public class PlatformDdl_AlterColumnTest { @@ -29,6 +31,30 @@ AlterColumn alterNotNull() { return alterColumn; } + @Test + public void convertArrayType_default() { + assertThat(mysqlDdl.convertArrayType("varchar[](90)")).isEqualTo("varchar(90)"); + assertThat(mysqlDdl.convertArrayType("integer[](60)")).isEqualTo("varchar(60)"); + assertThat(mysqlDdl.convertArrayType("varchar[]")).isEqualTo("varchar(1000)"); + assertThat(mysqlDdl.convertArrayType("integer[]")).isEqualTo("varchar(1000)"); + } + + @Test + public void convertArrayType_h2() { + assertThat(h2Ddl.convertArrayType("varchar[](90)")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("integer[](60)")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("varchar[]")).isEqualTo("array"); + assertThat(h2Ddl.convertArrayType("integer[]")).isEqualTo("array"); + } + + @Test + public void convertArrayType_postgres() { + assertThat(pgDdl.convertArrayType("varchar[](90)")).isEqualTo("varchar[]"); + assertThat(pgDdl.convertArrayType("integer[](60)")).isEqualTo("integer[]"); + assertThat(pgDdl.convertArrayType("varchar[]")).isEqualTo("varchar[]"); + assertThat(pgDdl.convertArrayType("integer[]")).isEqualTo("integer[]"); + } + @Test public void testAlterColumnBaseAttributes() throws Exception { diff --git a/src/test/resources/container/test-alter-table.xml b/src/test/resources/container/test-alter-table.xml index de71943e6c..5e8cb819bf 100644 --- a/src/test/resources/container/test-alter-table.xml +++ b/src/test/resources/container/test-alter-table.xml @@ -8,6 +8,22 @@ + + + + + + + + + + + + + + + + - \ No newline at end of file +