From dd8fff0277a12d0c5f01895e931ded5fc6b80df0 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Fri, 8 Sep 2017 11:47:33 +0200 Subject: [PATCH] Feature/ddl migration (#1111) * REFACTOR: use functions from ddl-help * NEW: Default values are written to DDL * fix testcase for sqlserver as default constraints will get names in future * Reading DbMigration * ADD: DbmIgrationGenerateTest * Tables must be created first * Sanity checks and some getters * DdlMigration gets applied now * ADD: Testcase and reference migration scripts * no effective code changes: add comments --- .../java/io/ebean/annotation/DbDefault.java | 23 +++ .../java/io/ebean/annotation/DbMigration.java | 65 +++++++ .../config/dbplatform/DatabasePlatform.java | 3 + .../config/dbplatform/DbDefaultValue.java | 132 ++++++++++++++ .../ddlgeneration/BaseDdlHandler.java | 7 + .../ddlgeneration/platform/BaseTableDdl.java | 132 +++++++++++++- .../ddlgeneration/platform/MySqlDdl.java | 6 +- .../ddlgeneration/platform/PlatformDdl.java | 50 ++++-- .../ddlgeneration/platform/SqlServerDdl.java | 11 +- .../dbmigration/migration/AlterColumn.java | 26 ++- .../ebean/dbmigration/migration/Column.java | 46 ++--- .../dbmigration/migration/DdlScript.java | 73 ++++++++ .../io/ebean/dbmigration/model/MColumn.java | 51 ++++++ .../build/ModelBuildPropertyVisitor.java | 4 +- .../server/deploy/BeanProperty.java | 14 +- .../server/deploy/DbMigrationInfo.java | 71 ++++++++ .../deploy/meta/DeployBeanProperty.java | 24 ++- .../server/deploy/parse/AnnotationFields.java | 19 ++ .../dbmigration/DbMigrationGenerateTest.java | 109 ++++++++++++ .../io/ebean/dbmigration/DbMigrationTest.java | 131 ++++++++++++-- .../ddlgeneration/BaseDdlHandlerTest.java | 3 +- .../platform/PlatformDdl_AlterColumnTest.java | 4 +- src/test/java/misc/migration/v1_0/EBasic.java | 116 +++++++++++++ .../java/misc/migration/v1_0/EHistory.java | 17 ++ src/test/java/misc/migration/v1_0/ERef.java | 19 ++ src/test/java/misc/migration/v1_1/EBasic.java | 162 ++++++++++++++++++ .../java/misc/migration/v1_1/EHistory.java | 26 +++ src/test/java/misc/migration/v1_1/EUser.java | 13 ++ src/test/java/misc/migration/v1_2/EBasic.java | 118 +++++++++++++ .../java/misc/migration/v1_2/EHistory.java | 17 ++ src/test/java/misc/migration/v1_2/ERef.java | 19 ++ .../migrationtest/db2/1.0__initial.sql | 39 +++++ .../dbmigration/migrationtest/db2/1.1.sql | 39 +++++ .../migrationtest/db2/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/db2/1.3.sql | 30 ++++ .../migrationtest/db2/1.4__dropsFor_1.3.sql | 12 ++ .../migrationtest/db2/R__order_views.sql | 8 + .../migrationtest/h2/1.0__initial.sql | 39 +++++ .../dbmigration/migrationtest/h2/1.1.sql | 50 ++++++ .../migrationtest/h2/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/h2/1.3.sql | 30 ++++ .../migrationtest/h2/1.4__dropsFor_1.3.sql | 20 +++ .../migrationtest/h2/R__multi_comments.sql | 3 + .../migrationtest/h2/R__order_views.sql | 8 + .../migrationtest/hsqldb/1.0__initial.sql | 39 +++++ .../dbmigration/migrationtest/hsqldb/1.1.sql | 39 +++++ .../hsqldb/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/hsqldb/1.3.sql | 30 ++++ .../hsqldb/1.4__dropsFor_1.3.sql | 12 ++ .../hsqldb/R__order_views_hsqldb.sql | 8 + .../model/1.0__initial.model.xml | 34 ++++ .../migrationtest/model/1.1.model.xml | 41 +++++ .../model/1.2__dropsFor_1.1.model.xml | 10 ++ .../migrationtest/model/1.3.model.xml | 33 ++++ .../model/1.4__dropsFor_1.3.model.xml | 13 ++ .../migrationtest/mysql/1.0__initial.sql | 39 +++++ .../dbmigration/migrationtest/mysql/1.1.sql | 57 ++++++ .../migrationtest/mysql/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/mysql/1.3.sql | 27 +++ .../migrationtest/mysql/1.4__dropsFor_1.3.sql | 21 +++ .../migrationtest/mysql/R__order_views.sql | 8 + .../migrationtest/oracle/1.0__initial.sql | 42 +++++ .../dbmigration/migrationtest/oracle/1.1.sql | 40 +++++ .../oracle/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/oracle/1.3.sql | 31 ++++ .../oracle/1.4__dropsFor_1.3.sql | 12 ++ .../oracle/R__oracle_only_views.sql | 3 + .../migrationtest/oracle/R__order_views.sql | 8 + .../migrationtest/postgres/1.0__initial.sql | 39 +++++ .../migrationtest/postgres/1.1.sql | 62 +++++++ .../postgres/1.2__dropsFor_1.1.sql | 8 + .../migrationtest/postgres/1.3.sql | 30 ++++ .../postgres/1.4__dropsFor_1.3.sql | 21 +++ .../postgres/R__multi_comments.sql | 3 + .../migrationtest/postgres/R__order_views.sql | 8 + .../migrationtest/postgres/R__pg_indexes.sql | 4 + .../migrationtest/sqlite/1.0__initial.sql | 37 ++++ .../dbmigration/migrationtest/sqlite/1.1.sql | 36 ++++ .../sqlite/1.2__dropsFor_1.1.sql | 8 + .../dbmigration/migrationtest/sqlite/1.3.sql | 28 +++ .../sqlite/1.4__dropsFor_1.3.sql | 12 ++ .../sqlite/R__order_views_sqlite.sql | 9 + .../migrationtest/sqlserver/1.0__initial.sql | 39 +++++ .../migrationtest/sqlserver/1.1.sql | 42 +++++ .../sqlserver/1.2__dropsFor_1.1.sql | 8 + .../migrationtest/sqlserver/1.3.sql | 27 +++ .../sqlserver/1.4__dropsFor_1.3.sql | 15 ++ .../sqlserver/R__order_views_mssql.sql | 10 ++ src/test/resources/ebean.mf | 2 +- src/test/resources/ebean.properties | 13 ++ 90 files changed, 2767 insertions(+), 70 deletions(-) create mode 100644 src/main/java/io/ebean/annotation/DbDefault.java create mode 100644 src/main/java/io/ebean/annotation/DbMigration.java create mode 100644 src/main/java/io/ebean/dbmigration/migration/DdlScript.java create mode 100644 src/main/java/io/ebeaninternal/server/deploy/DbMigrationInfo.java create mode 100644 src/test/java/io/ebean/dbmigration/DbMigrationGenerateTest.java create mode 100644 src/test/java/misc/migration/v1_0/EBasic.java create mode 100644 src/test/java/misc/migration/v1_0/EHistory.java create mode 100644 src/test/java/misc/migration/v1_0/ERef.java create mode 100644 src/test/java/misc/migration/v1_1/EBasic.java create mode 100644 src/test/java/misc/migration/v1_1/EHistory.java create mode 100644 src/test/java/misc/migration/v1_1/EUser.java create mode 100644 src/test/java/misc/migration/v1_2/EBasic.java create mode 100644 src/test/java/misc/migration/v1_2/EHistory.java create mode 100644 src/test/java/misc/migration/v1_2/ERef.java create mode 100644 src/test/resources/dbmigration/migrationtest/db2/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/db2/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/db2/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/db2/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/db2/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/db2/R__order_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/R__multi_comments.sql create mode 100644 src/test/resources/dbmigration/migrationtest/h2/R__order_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/hsqldb/R__order_views_hsqldb.sql create mode 100644 src/test/resources/dbmigration/migrationtest/model/1.0__initial.model.xml create mode 100644 src/test/resources/dbmigration/migrationtest/model/1.1.model.xml create mode 100644 src/test/resources/dbmigration/migrationtest/model/1.2__dropsFor_1.1.model.xml create mode 100644 src/test/resources/dbmigration/migrationtest/model/1.3.model.xml create mode 100644 src/test/resources/dbmigration/migrationtest/model/1.4__dropsFor_1.3.model.xml create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/mysql/R__order_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/R__oracle_only_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/oracle/R__order_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/R__multi_comments.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/R__order_views.sql create mode 100644 src/test/resources/dbmigration/migrationtest/postgres/R__pg_indexes.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlite/R__order_views_sqlite.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/1.0__initial.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/1.2__dropsFor_1.1.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/1.4__dropsFor_1.3.sql create mode 100644 src/test/resources/dbmigration/migrationtest/sqlserver/R__order_views_mssql.sql diff --git a/src/main/java/io/ebean/annotation/DbDefault.java b/src/main/java/io/ebean/annotation/DbDefault.java new file mode 100644 index 000000000..d330352d9 --- /dev/null +++ b/src/main/java/io/ebean/annotation/DbDefault.java @@ -0,0 +1,23 @@ +package io.ebean.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to specify a default value for DDL-generation & Migration. + * This annotation is EXPERMIENTAL and may change. + * + * TODO: Move this annotation to eben-annotation package + * + * @author Roland Praml, FOCONIS AG + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DbDefault { + /** + * The defaultValue for the column. + */ + String value(); +} diff --git a/src/main/java/io/ebean/annotation/DbMigration.java b/src/main/java/io/ebean/annotation/DbMigration.java new file mode 100644 index 000000000..e251acafa --- /dev/null +++ b/src/main/java/io/ebean/annotation/DbMigration.java @@ -0,0 +1,65 @@ +package io.ebean.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import io.ebean.Platform; + +/** + * Annotation to specify details for DDL & Migration-generation. (e.g. defaults/renames/...) + * This annotation is EXPERMIENTAL and may change. + * + * @author Roland Praml, FOCONIS AG + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +@Repeatable(DbMigration.List.class) +public @interface DbMigration { + + /** + * DdlScripts that will be executed before the 'alter' command. + * + * You may write a custom update routine here. + * If you do not specify an SQL here, and this will alter the table + * to a non-null column, ebean will autogenerate a statement from + * default value like this: + *
+   * UPDATE table SET column = 'foo' WHERE column IS NULL
+   * 
+ */ + String[] preAlter() default {}; + + /** + * DdlScript that will be executed after the 'alter' command + */ + String[] postAlter() default {}; + + /** + * DdlScript that will be executed before the 'add' command + */ + String[] preAdd() default {}; + + /** + * DdlScript that will be executed after the 'add' command. + * You may write certain update scripts here. + */ + String[] postAdd() default {}; + + // TODO: Do we need preDrop / postDrop? + + + Platform[] platforms() default {}; + + /** + * Repeatable support for {@link Formula}. + */ + @Target({ ElementType.FIELD }) + @Retention(RetentionPolicy.RUNTIME) + @interface List { + + DbMigration[] value() default {}; + } +} diff --git a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java index c011db70f..f2d44df55 100644 --- a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java +++ b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java @@ -287,6 +287,9 @@ public class DatabasePlatform { * Create and return a DDL handler for generating DDL scripts. */ public DdlHandler createDdlHandler(ServerConfig serverConfig) { + if (platformDdl == null) { + throw new IllegalStateException("Platform " + getName() + " has no DDL Handler"); + } return platformDdl.createDdlHandler(serverConfig); } diff --git a/src/main/java/io/ebean/config/dbplatform/DbDefaultValue.java b/src/main/java/io/ebean/config/dbplatform/DbDefaultValue.java index ccd6fb505..f478bb7a6 100644 --- a/src/main/java/io/ebean/config/dbplatform/DbDefaultValue.java +++ b/src/main/java/io/ebean/config/dbplatform/DbDefaultValue.java @@ -1,8 +1,13 @@ package io.ebean.config.dbplatform; +import java.sql.Types; import java.util.LinkedHashMap; import java.util.Map; +import javax.xml.bind.DatatypeConverter; + +import io.ebean.annotation.DbDefault; + /** * DB Column default values mapping to database platform specific literals. */ @@ -22,6 +27,13 @@ public class DbDefaultValue { * The key for the NOW / current timestamp. */ public static final String NOW = "now"; + + /** + * The 'null' literal. + */ + public static final String NULL = "null"; + + protected Map map = new LinkedHashMap<>(); @@ -63,8 +75,128 @@ public class DbDefaultValue { if (dbDefaultLiteral == null) { return null; } + if (dbDefaultLiteral.startsWith("$RAW:")) { + return dbDefaultLiteral.substring(5); + } String val = map.get(dbDefaultLiteral); return val != null ? val : dbDefaultLiteral; } + + /** + * This method checks & convert the {@link DbDefault#value()} to a valid SQL literal. + * + * This is mainly to quote string literals and verify integer/dates for correctness. + *

+ * Note: There are some special cases: + *

+ * + */ + public static String toSqlLiteral(String defaultValue, Class propertyType, int sqlType) { + if (propertyType == null + || defaultValue == null + || NULL.equals(defaultValue) + || (defaultValue.startsWith("'") && defaultValue.endsWith("'")) + || (defaultValue.startsWith("$RAW:"))) { + return defaultValue; + } + + if (Boolean.class.isAssignableFrom(propertyType) || Boolean.TYPE.isAssignableFrom(propertyType)) { + return toBooleanLiteral(defaultValue); + } + + if (Number.class.isAssignableFrom(propertyType) + || Byte.TYPE.equals(propertyType) + || Short.TYPE.equals(propertyType) + || Integer.TYPE.equals(propertyType) + || Long.TYPE.equals(propertyType) + || Float.TYPE.equals(propertyType) + || Double.TYPE.equals(propertyType) + || (propertyType.isEnum() && sqlType == Types.INTEGER)) { + Double.valueOf(defaultValue); // verify if it is a number + return defaultValue; + } + + // check if it is a date/time - in all other cases return quoted defaultValue + switch (sqlType) { + // date + case Types.DATE: + return toDateLiteral(defaultValue); + // time + case Types.TIME: + case Types.TIME_WITH_TIMEZONE: + return toTimeLiteral(defaultValue); + // timestamp + case Types.TIMESTAMP: + case Types.TIMESTAMP_WITH_TIMEZONE: + return toDateTimeLiteral(defaultValue); + + default: + return toTextLiteral(defaultValue); // do not check other datatypes + } + } + + /** + * Checks if specified value is either 'true' or 'false'. The literal is translated later. + */ + private static String toBooleanLiteral(String value) { + if (DbDefaultValue.FALSE.equals(value) || DbDefaultValue.TRUE.equals(value)) { + return value; + } + throw new IllegalArgumentException("'" + value + "' is not a valid value for boolean"); + } + + /** + * This adds single qoutes around the value and doubles single quotes. + * "User's home" will return "'User''s home'" + */ + private static String toTextLiteral(String value) { + StringBuilder sb = new StringBuilder(value.length()+10); + sb.append('\''); + for (int i = 0; i < value.length(); i++) { + char ch = value.charAt(i); + if (ch == '\'') { + sb.append("''"); + } else { + sb.append(ch); + } + } + sb.append('\''); + return sb.toString(); + + } + + private static String toDateLiteral(String value) { + if (NOW.equals(value)) { + return value; // this will get translated later + } + DatatypeConverter.parseDate(value); // verify + return toTextLiteral(value); + } + + private static String toTimeLiteral(String value) { + if (NOW.equals(value)) { + return value; // this will get translated later + } + DatatypeConverter.parseTime(value); // verify + return toTextLiteral(value); + } + + private static String toDateTimeLiteral(String value) { + if (NOW.equals(value)) { + return value; // this will get translated later + } + DatatypeConverter.parseDateTime(value); // verify + return toTextLiteral(value); + } } diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java index 350df1db9..6effd8e43 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java @@ -36,6 +36,11 @@ public class BaseDdlHandler implements DdlHandler { for (Object change : changeSetChildren) { if (change instanceof CreateTable) { generate(writer, (CreateTable) change); + } + } + for (Object change : changeSetChildren) { + if (change instanceof CreateTable) { + // ignore } else if (change instanceof DropTable) { generate(writer, (DropTable) change); } else if (change instanceof AddTableComment) { @@ -54,6 +59,8 @@ public class BaseDdlHandler implements DdlHandler { generate(writer, (AddHistoryTable) change); } else if (change instanceof DropHistoryTable) { generate(writer, (DropHistoryTable) change); + } else { + throw new IllegalArgumentException("Unsupported change: " + change); } } } diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java index b7798b511..1ca30a410 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -15,6 +15,7 @@ import io.ebean.dbmigration.migration.AlterColumn; import io.ebean.dbmigration.migration.Column; import io.ebean.dbmigration.migration.CreateIndex; import io.ebean.dbmigration.migration.CreateTable; +import io.ebean.dbmigration.migration.DdlScript; import io.ebean.dbmigration.migration.DropColumn; import io.ebean.dbmigration.migration.DropHistoryTable; import io.ebean.dbmigration.migration.DropIndex; @@ -27,6 +28,8 @@ import io.ebean.util.StringHelper; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -70,6 +73,119 @@ public class BaseTableDdl implements TableDdl { */ protected Map regenerateHistoryTriggers = new LinkedHashMap<>(); + private boolean strict; + + /** + * Helper class that is used to execute the migration ddl before and after the migration action. + */ + private class DdlMigrationHelp { + private List before; + private List after; + private String tableName; + private String columnName; + private String defaultValue; + + /** + * Constructor for DdlMigrationHelp when adding a NEW column. + */ + DdlMigrationHelp(String tableName, Column column) throws IOException { + this.tableName = tableName; + this.columnName = column.getName(); + this.defaultValue = platformDdl.convertDefaultValue(column.getDefaultValue()); + boolean alterNotNull = Boolean.TRUE.equals(column.isNotnull()); + + if (column.getBefore().isEmpty() && alterNotNull && defaultValue == null) { + handleStrictError("non-null column has no default value: " + tableName + "." + columnName); + } + + before = getScriptsForPlatform(column.getBefore(), platformDdl.getPlatform().getName()); + after = getScriptsForPlatform(column.getAfter(), platformDdl.getPlatform().getName()); + + } + + /** + * Constructor for DdlMigrationHelp when altering a column. + */ + DdlMigrationHelp(AlterColumn alter) throws IOException { + this.tableName = alter.getTableName(); + this.columnName = alter.getColumnName(); + + String tmp = alter.getDefaultValue() != null ? alter.getDefaultValue() : alter.getCurrentDefaultValue(); + this.defaultValue = platformDdl.convertDefaultValue(tmp); + + boolean alterNotNull = Boolean.TRUE.equals(alter.isNotnull()); + // here we add the platform's default update script + if (alter.getBefore().isEmpty() && alterNotNull) { + if (defaultValue == null) { + handleStrictError("non-null column has no default value: " + tableName + "." + columnName); + } + before = Arrays.asList(platformDdl.getUpdateNullWithDefault()); + } else { + before = getScriptsForPlatform(alter.getBefore(), platformDdl.getPlatform().getName()); + } + + after = getScriptsForPlatform(alter.getAfter(), platformDdl.getPlatform().getName()); + + } + + public void writeBefore(DdlBuffer buffer) throws IOException { + if (!before.isEmpty()) { + buffer.end(); + } + for (String ddlScript : before) { + buffer.append(translate(ddlScript, tableName, columnName, this.defaultValue)); + buffer.endOfStatement(); + } + } + + public void writeAfter(DdlBuffer buffer) throws IOException { + // here we run postmigration scripts + for (String ddlScript : after) { + buffer.append(translate(ddlScript, tableName, columnName, defaultValue)); + buffer.endOfStatement(); + } + if (!after.isEmpty()) { + buffer.end(); + } + } + + private List getScriptsForPlatform(List scripts, String searchPlatform) { + List ret = Collections.emptyList(); + for (DdlScript script : scripts) { + if (script.getPlatforms() == null || script.getPlatforms().isEmpty()) { + ret = script.getDdl(); + } else for (String platform : StringHelper.splitNames(script.getPlatforms())) { + if (platform.equals(searchPlatform)) { + return script.getDdl(); + } + } + } + return ret; + } + + /** + * Replaces Table name (${table}), Column name (${column}) and default value (${default}) in DDL. + */ + private String translate(String ddl, String tableName, String columnName, String defaultValue) { + String ret = StringHelper.replaceString(ddl, "${table}", tableName); + ret = StringHelper.replaceString(ret, "${column}", columnName); + return StringHelper.replaceString(ret, "${default}", defaultValue); + } + + private void handleStrictError(String message) { + if (strict) { + throw new IllegalArgumentException(message); + } else { + System.err.println("Error in DDL: " + message); + } + } + + public String getDefaultValue() { + return defaultValue; + } + + } + /** * Construct with a naming convention and platform specific DDL. */ @@ -79,6 +195,7 @@ public class BaseTableDdl implements TableDdl { this.historyTableSuffix = serverConfig.getHistoryTableSuffix(); this.platformDdl = platformDdl; this.platformDdl.configure(serverConfig); + this.strict = true; // TODO RPr serverConfig.getMigrationConfig().isStrict(); } /** @@ -649,7 +766,9 @@ public class BaseTableDdl implements TableDdl { */ @Override public void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException { - + DdlMigrationHelp ddlHelp = new DdlMigrationHelp(alterColumn); + ddlHelp.writeBefore(writer.apply()); + if (isTrue(alterColumn.isHistoryExclude())) { regenerateHistoryTriggers(alterColumn.getTableName(), HistoryTableUpdate.Change.EXCLUDE, alterColumn.getColumnName()); } else if (isFalse(alterColumn.isHistoryExclude())) { @@ -702,6 +821,7 @@ public class BaseTableDdl implements TableDdl { // add constraint last (after potential type change) addCheckConstraint(writer, alterColumn); } + ddlHelp.writeAfter(writer.apply()); } private void alterColumnComment(DdlWrite writer, AlterColumn alterColumn) throws IOException { @@ -856,11 +976,11 @@ public class BaseTableDdl implements TableDdl { } protected void alterTableAddColumn(DdlBuffer buffer, String tableName, Column column, boolean onHistoryTable) throws IOException { - String ddl = platformDdl.alterTableAddColumn(tableName, column, onHistoryTable); - if (hasValue(ddl)) { - buffer.append(ddl); - buffer.endOfStatement(); - } + DdlMigrationHelp help = new DdlMigrationHelp(tableName, column); + help.writeBefore(buffer); + platformDdl.alterTableAddColumn(buffer, tableName, column, onHistoryTable, help.getDefaultValue()); + + help.writeAfter(buffer); } protected boolean isFalse(Boolean value) { diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/MySqlDdl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/MySqlDdl.java index dbd890762..e10d0f507 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/MySqlDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/MySqlDdl.java @@ -59,7 +59,7 @@ public class MySqlDdl extends PlatformDdl { @Override public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) { - String suffix = isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + defaultValue; + String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + defaultValue; // use alter return "alter table " + tableName + " alter " + columnName + " " + suffix; @@ -67,7 +67,9 @@ public class MySqlDdl extends PlatformDdl { @Override public String alterColumnBaseAttributes(AlterColumn alter) { - + if (DdlHelp.isDropDefault(alter.getDefaultValue())) { + return null; + } String tableName = alter.getTableName(); String columnName = alter.getColumnName(); String type = alter.getType() != null ? alter.getType() : alter.getCurrentType(); 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 258e5bec6..63855b2e9 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -87,6 +87,8 @@ public class PlatformDdl { protected String columnSetNotnull = "set not null"; protected String columnSetNull = "set null"; + + protected String updateNullWithDefault = "update ${table} set ${column} = ${default} where ${column} is null"; /** * Set false for MsSqlServer to allow multiple nulls for OneToOne mapping. @@ -205,7 +207,7 @@ public class PlatformDdl { /** * Convert the DB column default literal to platform specific. */ - private String convertDefaultValue(String dbDefault) { + public String convertDefaultValue(String dbDefault) { return dbDefaultValue.convert(dbDefault); } @@ -379,25 +381,38 @@ public class PlatformDdl { return buffer.toString(); } - public String alterTableAddColumn(String tableName, Column column, boolean onHistoryTable) throws IOException { + public void alterTableAddColumn(DdlBuffer buffer, String tableName, Column column, boolean onHistoryTable, String defaultValue) throws IOException { String convertedType = convert(column.getType(), false); - StringBuilder buffer = new StringBuilder(90); buffer.append("alter table ").append(tableName) - .append(' ').append(addColumn).append(' ').append(column.getName()) - .append(' ').append(convertedType); + .append(" ").append(addColumn).append(" ").append(column.getName()) + .append(" ").append(convertedType); if (!onHistoryTable) { if (isTrue(column.isNotnull())) { buffer.append(" not null"); } - if (!StringHelper.isNull(column.getCheckConstraint())) { - buffer.append(" constraint ").append(column.getCheckConstraintName()); - buffer.append(" ").append(column.getCheckConstraint()); + + if (defaultValue != null) { + if (typeContainsDefault(convertedType)) { + System.err.println("Cannot set default value for '" + tableName + "." + column.getName() + "'"); + } else { + buffer.append(" default "); + buffer.append(defaultValue); + } } + buffer.endOfStatement(); + + // check constraints cannot be added in one statement for h2 + if (!StringHelper.isNull(column.getCheckConstraint())) { + String ddl = alterTableAddCheckConstraint(tableName, column.getCheckConstraintName(), column.getCheckConstraint()); + buffer.append(ddl).endOfStatement(); + } + } else { + buffer.endOfStatement(); } - return buffer.toString(); + } /** @@ -440,19 +455,11 @@ public class PlatformDdl { return "alter table " + tableName + " " + addConstraint + " " + checkConstraintName + " " + checkConstraint; } - /** - * Return true if the default value is the special DROP DEFAULT value. - */ - public boolean isDropDefault(String defaultValue) { - return "DROP DEFAULT".equals(defaultValue); - } - /** * Alter column setting the default value. */ public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) { - - String suffix = isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + defaultValue; + String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + defaultValue; return "alter table " + tableName + " " + alterColumn + " " + columnName + " " + suffix; } @@ -505,6 +512,13 @@ public class PlatformDdl { return naming.lowerColumnName(name); } + public DatabasePlatform getPlatform() { + return platform; + } + + public String getUpdateNullWithDefault() { + return updateNullWithDefault; + } /** * Null safe Boolean true test. diff --git a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/SqlServerDdl.java b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/SqlServerDdl.java index 02dfe516a..5ca2a5b16 100644 --- a/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/SqlServerDdl.java +++ b/src/main/java/io/ebean/dbmigration/ddlgeneration/platform/SqlServerDdl.java @@ -103,16 +103,19 @@ public class SqlServerDdl extends PlatformDdl { @Override public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) { - if (isDropDefault(defaultValue)) { - return "-- alter table " + tableName + " drop constraint -- find the appropriate constraint for default value on column " + columnName; + if (DdlHelp.isDropDefault(defaultValue)) { + return "alter table " + tableName + " drop constraint df_" + tableName + "_" + columnName; } else { - return "alter table " + tableName + " add default " + defaultValue + " for " + columnName; + return "alter table " + tableName + " add constraint df_" + tableName + "_" + columnName + + " default " + defaultValue + " for " + columnName; } } @Override public String alterColumnBaseAttributes(AlterColumn alter) { - + if (DdlHelp.isDropDefault(alter.getDefaultValue())) { + return null; + } String tableName = alter.getTableName(); String columnName = alter.getColumnName(); String type = alter.getType() != null ? alter.getType() : alter.getCurrentType(); diff --git a/src/main/java/io/ebean/dbmigration/migration/AlterColumn.java b/src/main/java/io/ebean/dbmigration/migration/AlterColumn.java index 4a869abb1..28d359f6a 100644 --- a/src/main/java/io/ebean/dbmigration/migration/AlterColumn.java +++ b/src/main/java/io/ebean/dbmigration/migration/AlterColumn.java @@ -1,8 +1,12 @@ package io.ebean.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; @@ -44,10 +48,17 @@ import javax.xml.bind.annotation.XmlType; * */ @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "") +@XmlType(name = "", propOrder = { + "before", "after" +}) @XmlRootElement(name = "alterColumn") public class AlterColumn { + @XmlElement(required = false) + protected List before; + @XmlElement(required = false) + protected List after; + @XmlAttribute(name = "columnName", required = true) protected String columnName; @XmlAttribute(name = "tableName", required = true) @@ -533,4 +544,17 @@ public class AlterColumn { this.dropForeignKeyIndex = value; } + public List getBefore() { + if (before == null) { + before = new ArrayList<>(); + } + return before; + } + + public List getAfter() { + if (after == null) { + after = new ArrayList<>(); + } + return after; + } } diff --git a/src/main/java/io/ebean/dbmigration/migration/Column.java b/src/main/java/io/ebean/dbmigration/migration/Column.java index 4570ef822..4a16eaa0f 100644 --- a/src/main/java/io/ebean/dbmigration/migration/Column.java +++ b/src/main/java/io/ebean/dbmigration/migration/Column.java @@ -1,8 +1,12 @@ package io.ebean.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 javax.xml.bind.annotation.XmlValue; @@ -39,13 +43,16 @@ import javax.xml.bind.annotation.XmlValue; */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { - "content" + "before", "after" }) @XmlRootElement(name = "column") public class Column { - - @XmlValue - protected String content; + + @XmlElement(required = false) + protected List before; + @XmlElement(required = false) + protected List after; + @XmlAttribute(name = "name", required = true) protected String name; @XmlAttribute(name = "type", required = true) @@ -76,27 +83,22 @@ public class Column { protected String foreignKeyIndex; @XmlAttribute(name = "comment") protected String comment; + - /** - * Gets the value of the content property. - * - * @return possible object is - * {@link String } - */ - public String getContent() { - return content; + public List getBefore() { + if (before == null) { + before = new ArrayList<>(); + } + return before; } - - /** - * Sets the value of the content property. - * - * @param value allowed object is - * {@link String } - */ - public void setContent(String value) { - this.content = value; + + public List getAfter() { + if (after == null) { + after = new ArrayList<>(); + } + return after; } - + /** * Gets the value of the name property. * diff --git a/src/main/java/io/ebean/dbmigration/migration/DdlScript.java b/src/main/java/io/ebean/dbmigration/migration/DdlScript.java new file mode 100644 index 000000000..479b8e29e --- /dev/null +++ b/src/main/java/io/ebean/dbmigration/migration/DdlScript.java @@ -0,0 +1,73 @@ +package io.ebean.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.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + + +/** + *

Java class for anonymous complex type. + *

+ *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * TODO @Rob: Can this generated automatically?
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "ddl" +}) +@XmlRootElement(name = "ddl-script") +public class DdlScript { + + @XmlValue + protected List ddl; + + @XmlAttribute(name = "platforms") + protected String platforms; + + /** + * Gets the value of the value property. + * + * @return possible object is + * {@link String } + */ + public List getDdl() { + if (ddl == null) { + ddl = new ArrayList<>(); + } + return ddl; + } + + public void setDdl(List ddl) { + this.ddl = ddl; + } + + /** + * Gets the value of the platforms property. + * + * @return possible object is + * {@link String } + */ + public String getPlatforms() { + return platforms; + } + + /** + * Sets the value of the platforms property. + * + * @param value allowed object is + * {@link String } + */ + public void setPlatforms(String value) { + this.platforms = value; + } + +} diff --git a/src/main/java/io/ebean/dbmigration/model/MColumn.java b/src/main/java/io/ebean/dbmigration/model/MColumn.java index 22f05de9c..7915c09f1 100644 --- a/src/main/java/io/ebean/dbmigration/model/MColumn.java +++ b/src/main/java/io/ebean/dbmigration/model/MColumn.java @@ -1,8 +1,14 @@ package io.ebean.dbmigration.model; +import java.util.List; + +import javax.sound.midi.MidiDevice.Info; + import io.ebean.dbmigration.ddlgeneration.platform.DdlHelp; import io.ebean.dbmigration.migration.AlterColumn; import io.ebean.dbmigration.migration.Column; +import io.ebean.dbmigration.migration.DdlScript; +import io.ebeaninternal.server.deploy.DbMigrationInfo; /** * A column in the logical model. @@ -38,6 +44,8 @@ public class MColumn { private AlterColumn alterColumn; private boolean draftOnly; + + private List dbMigrationInfos; public MColumn(Column column) { this.name = column.getName(); @@ -78,6 +86,7 @@ public class MColumn { copy.checkConstraint = checkConstraint; copy.checkConstraintName = checkConstraintName; copy.defaultValue = defaultValue; + copy.dbMigrationInfos = dbMigrationInfos; copy.references = references; copy.comment = comment; copy.foreignKeyName = foreignKeyName; @@ -257,6 +266,24 @@ public class MColumn { c.setComment(comment); c.setUnique(unique); c.setUniqueOneToOne(uniqueOneToOne); + + if (dbMigrationInfos != null) { + for (DbMigrationInfo info : dbMigrationInfos) { + if (!info.getPreAdd().isEmpty()) { + DdlScript script = new DdlScript(); + script.setDdl(info.getPreAdd()); + script.setPlatforms(info.joinPlatforms()); + c.getBefore().add(script); + } + + if (!info.getPostAdd().isEmpty()) { + DdlScript script = new DdlScript(); + script.setDdl(info.getPostAdd()); + script.setPlatforms(info.joinPlatforms()); + c.getAfter().add(script); + } + } + } return c; } @@ -281,6 +308,24 @@ public class MColumn { if (tableWithHistory) { alterColumn.setWithHistory(Boolean.TRUE); } + + if (dbMigrationInfos != null) { + for (DbMigrationInfo info : dbMigrationInfos) { + if (!info.getPreAlter().isEmpty()) { + DdlScript script = new DdlScript(); + script.setDdl(info.getPreAlter()); + script.setPlatforms(info.joinPlatforms()); + alterColumn.getBefore().add(script); + } + + if (!info.getPostAlter().isEmpty()) { + DdlScript script = new DdlScript(); + script.setDdl(info.getPostAlter()); + script.setPlatforms(info.joinPlatforms()); + alterColumn.getAfter().add(script); + } + } + } } return alterColumn; } @@ -291,6 +336,8 @@ public class MColumn { */ public void compare(ModelDiff modelDiff, MTable table, MColumn newColumn) { + this.dbMigrationInfos = newColumn.dbMigrationInfos; + boolean tableWithHistory = table.isWithHistory(); String tableName = table.getName(); @@ -383,6 +430,10 @@ public class MColumn { } } + public void setDbMigrationInfos(List dbMigrationInfos) { + this.dbMigrationInfos = dbMigrationInfos; + } + /** * Apply changes based on the AlterColumn request. */ diff --git a/src/main/java/io/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java b/src/main/java/io/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java index b867eff57..bd54f7f5f 100644 --- a/src/main/java/io/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java +++ b/src/main/java/io/ebean/dbmigration/model/build/ModelBuildPropertyVisitor.java @@ -177,7 +177,8 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { String refColumn = importedProperty.getDbColumn(); MColumn col = table.addColumn(dbCol, columnDefn, !p.isNullable()); - + 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(); @@ -232,6 +233,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { } } else { col.setDefaultValue(p.getDbColumnDefault()); + col.setDbMigrationInfos(p.getDbMigrationInfos()); if (!p.isNullable() || p.isDDLNotNull()) { col.setNotnull(true); } diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java index 34676b8b2..68b52a6f4 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java +++ b/src/main/java/io/ebeaninternal/server/deploy/BeanProperty.java @@ -2,9 +2,11 @@ package io.ebeaninternal.server.deploy; import com.fasterxml.jackson.core.JsonToken; import io.ebean.ValuePair; +import io.ebean.annotation.DbDefault; import io.ebean.bean.EntityBean; import io.ebean.bean.PersistenceContext; import io.ebean.config.EncryptKey; +import io.ebean.config.dbplatform.DbDefaultValue; import io.ebean.config.dbplatform.DbEncryptFunction; import io.ebean.config.dbplatform.DbPlatformType; import io.ebean.plugin.Property; @@ -232,6 +234,7 @@ public class BeanProperty implements ElPropertyValue, Property { * DB Column default value for DDL definition (FALSE, NOW etc). */ final String dbColumnDefault; + final List dbMigrationInfos; /** * Database DDL column comment. @@ -303,7 +306,8 @@ public class BeanProperty implements ElPropertyValue, Property { this.dbLength = deploy.getDbLength(); this.dbScale = deploy.getDbScale(); this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn()); - this.dbColumnDefault = deploy.getDbColumnDefault(); + this.dbColumnDefault = DbDefaultValue.toSqlLiteral(deploy.getDbColumnDefault(), deploy.getPropertyType(), deploy.getDbType()); + this.dbMigrationInfos = deploy.getDbMigrationInfos(); this.inherited = false;// deploy.isInherited(); this.owningType = deploy.getOwningType(); @@ -414,6 +418,7 @@ public class BeanProperty implements ElPropertyValue, Property { this.dbScale = source.getDbScale(); this.dbColumnDefn = InternString.intern(source.getDbColumnDefn()); this.dbColumnDefault = source.dbColumnDefault; + this.dbMigrationInfos = source.dbMigrationInfos; this.inherited = source.isInherited(); this.owningType = source.owningType; @@ -1033,6 +1038,13 @@ public class BeanProperty implements ElPropertyValue, Property { return dbColumnDefn != null ? null : dbColumnDefault; } + /** + * Return the DDL-Migration Infos + */ + public List getDbMigrationInfos() { + return dbMigrationInfos; + } + /** * Return the bean Field associated with this property. */ diff --git a/src/main/java/io/ebeaninternal/server/deploy/DbMigrationInfo.java b/src/main/java/io/ebeaninternal/server/deploy/DbMigrationInfo.java new file mode 100644 index 000000000..ef8e3ebc9 --- /dev/null +++ b/src/main/java/io/ebeaninternal/server/deploy/DbMigrationInfo.java @@ -0,0 +1,71 @@ +package io.ebeaninternal.server.deploy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import io.ebean.Platform; +/** + * Class to hold the DDL-migration information that is needed to do correct alters. + * + * @author Roland Praml, FOCONIS AG + */ +public class DbMigrationInfo { + + private final List preAdd; + private final List postAdd; + private final List preAlter; + private final List postAlter; + private final List platforms; + + public DbMigrationInfo(String[] preAdd, String[] postAdd, String[] preAlter, String[] postAlter, Platform[] platforms) { + this.preAdd = toList(preAdd); + this.postAdd = toList(postAdd); + this.preAlter = toList(preAlter); + this.postAlter = toList(postAlter); + this.platforms = toList(platforms); + } + + private List toList(T[] scripts) { + if (scripts.length == 0) { + return Collections.emptyList(); + } else { + return Collections.unmodifiableList(Arrays.asList(scripts)); + } + } + + public List getPreAdd() { + return preAdd; + } + public List getPostAdd() { + return postAdd; + } + public List getPreAlter() { + return preAlter; + } + public List getPostAlter() { + return postAlter; + } + public List getPlatforms() { + return platforms; + } + + public String joinPlatforms() { + if (platforms.isEmpty()) { + return null; + } else { + StringBuilder sb = new StringBuilder(); + for (Platform p : platforms) { + if (sb.length() > 0) { + sb.append(','); + } + sb.append(p.name().toLowerCase()); + } + return sb.toString(); + } + } + + +} diff --git a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java index 2a08d742c..86eb6f338 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java +++ b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanProperty.java @@ -17,6 +17,7 @@ import io.ebean.config.dbplatform.DbEncryptFunction; import io.ebeaninternal.server.core.InternString; import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.DeployDocPropertyOptions; +import io.ebeaninternal.server.deploy.DbMigrationInfo; import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty; import io.ebeaninternal.server.deploy.parse.AnnotationBase; import io.ebeaninternal.server.el.ElPropertyValue; @@ -34,7 +35,9 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.sql.Types; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -221,6 +224,8 @@ public class DeployBeanProperty { private String dbColumnDefault; + private List dbMigrationInfos; + public DeployBeanProperty(DeployBeanDescriptor desc, Class propertyType, ScalarType scalarType, ScalarTypeConverter typeConverter) { this.desc = desc; this.propertyType = propertyType; @@ -949,7 +954,9 @@ public class DeployBeanProperty { public void checkPrimitiveBoolean() { if (boolean.class.equals(propertyType) && !softDelete) { this.nullable = false; - this.dbColumnDefault = DbDefaultValue.FALSE; + if (dbColumnDefault == null) { + this.dbColumnDefault = DbDefaultValue.FALSE; + } } else if (!id && !versionColumn && PRIMITIVE_NUMBER_TYPES.contains(propertyType)) { this.nullable = false; @@ -1003,6 +1010,10 @@ public class DeployBeanProperty { return dbColumnDefault; } + public void setDbColumnDefault(String dbColumnDefault) { + this.dbColumnDefault = dbColumnDefault; + } + public void setTenantId() { this.tenantId = true; this.nullable = false; @@ -1013,4 +1024,15 @@ public class DeployBeanProperty { public boolean isTenantId() { return tenantId; } + + public void addDbMigrationInfo(DbMigrationInfo info) { + if (dbMigrationInfos == null) { + dbMigrationInfos = new ArrayList<>(); + } + dbMigrationInfos.add(info); + } + + public List getDbMigrationInfos() { + return dbMigrationInfos; + } } diff --git a/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java b/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java index 6e061e14e..6bd798368 100644 --- a/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java +++ b/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationFields.java @@ -7,6 +7,7 @@ import io.ebean.config.dbplatform.DbEncrypt; import io.ebean.config.dbplatform.DbEncryptFunction; import io.ebean.config.dbplatform.IdType; import io.ebean.config.dbplatform.PlatformIdGenerator; +import io.ebeaninternal.server.deploy.DbMigrationInfo; import io.ebeaninternal.server.deploy.IndexDefinition; import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory; import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; @@ -131,6 +132,7 @@ public class AnnotationFields extends AnnotationParser { } initWhoProperties(prop); + readDbMigration(prop); } private void initWhoProperties(DeployBeanProperty prop) { @@ -287,14 +289,20 @@ public class AnnotationFields extends AnnotationParser { if (get(prop, HistoryExclude.class) != null) { prop.setExcludedFromHistory(); } + Length length = get(prop, Length.class); if (length != null) { prop.setDbLength(length.value()); } + io.ebean.annotation.NotNull nonNull = get(prop, io.ebean.annotation.NotNull.class); if (nonNull != null) { prop.setNullable(false); } + + readDbMigration(prop); + + if (validationAnnotations) { NotNull notNull = get(prop, NotNull.class); if (notNull != null && isEbeanValidationGroups(notNull.groups())) { @@ -346,6 +354,17 @@ public class AnnotationFields extends AnnotationParser { } } + private void readDbMigration(DeployBeanProperty prop) { + DbDefault dbDefault = get(prop, DbDefault.class); + if (dbDefault != null) { + prop.setDbColumnDefault(dbDefault.value()); + } + + Set dbMigration = getAll(prop, DbMigration.class); + dbMigration.forEach(ann -> prop.addDbMigrationInfo( + new DbMigrationInfo(ann.preAdd(), ann.postAdd(), ann.preAlter(), ann.postAlter(), ann.platforms()))); + } + private void addIndex(DeployBeanProperty prop, Index index) { String[] columnNames; if (index.columnNames().length == 0) { diff --git a/src/test/java/io/ebean/dbmigration/DbMigrationGenerateTest.java b/src/test/java/io/ebean/dbmigration/DbMigrationGenerateTest.java new file mode 100644 index 000000000..1d38b8ec7 --- /dev/null +++ b/src/test/java/io/ebean/dbmigration/DbMigrationGenerateTest.java @@ -0,0 +1,109 @@ +package io.ebean.dbmigration; + +import io.ebean.BaseTestCase; +import io.ebean.EbeanServer; +import io.ebean.EbeanServerFactory; +import io.ebean.Platform; +import io.ebean.config.ServerConfig; + +import org.junit.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; + + +/** + * This is the Migrationscript generator. It generates 3 migrationscript for the models + * @author Roland Praml, FOCONIS AG + * + */ +public class DbMigrationGenerateTest { + + private static final Logger logger = LoggerFactory.getLogger(DbMigrationGenerateTest.class); + + @Test + public void invokeTest() throws IOException { + main(null); + } + + public static void main(String[] args) throws IOException { + + logger.info("start"); + + DbMigration migration = new DbMigration(); + + // We use src/test/resources as output directory (so we see in GIT if files will change) + + migration.setPathToResources("src/test/resources"); + + + // migration.addPlatform(Platform.GENERIC, "generic"); there is no ddl handler for generic + // migration.addPlatform(Platform.SQLANYWHERE, "sqlanywhere"); and sqlanywhere + migration.addPlatform(Platform.DB2, "db2"); + migration.addPlatform(Platform.H2, "h2"); + migration.addPlatform(Platform.HSQLDB, "hsqldb"); + migration.addPlatform(Platform.MYSQL, "mysql"); + migration.addPlatform(Platform.POSTGRES, "postgres"); + migration.addPlatform(Platform.ORACLE, "oracle"); + migration.addPlatform(Platform.SQLITE, "sqlite"); + migration.addPlatform(Platform.SQLSERVER, "sqlserver"); + + ServerConfig config = new ServerConfig(); + config.setName("migrationtest"); + config.loadFromProperties(); + config.setRegister(false); + config.setDefaultServer(false); + + + config.setPackages(Arrays.asList("misc.migration.v1_0")); + EbeanServer server = EbeanServerFactory.create(config); + migration.setServer(server); + + // First, we clean up the output-directory + assertThat(migration.getMigrationDirectory().getAbsolutePath()).contains("migrationtest"); + Files.walk(migration.getMigrationDirectory().toPath()) + .filter(Files::isRegularFile).map(Path::toFile).forEach(File::delete); + + // then we generate migration scripts for v1_0 + assertThat(migration.generateMigration()).isEqualTo("1.0__initial"); + // and we check repeatative calls + assertThat(migration.generateMigration()).isNull(); + + // and now for v1_1 + config.setPackages(Arrays.asList("misc.migration.v1_1")); + server = EbeanServerFactory.create(config); + migration.setServer(server); + assertThat(migration.generateMigration()).isEqualTo("1.1"); + assertThat(migration.generateMigration()).isNull(); // subsequent call + + + + System.setProperty("ddl.migration.pendingDropsFor", "1.1"); + assertThat(migration.generateMigration()).isEqualTo("1.2__dropsFor_1.1"); + System.clearProperty("ddl.migration.pendingDropsFor"); + assertThat(migration.generateMigration()).isNull(); // subsequent call + + // and now for v1_2 with + config.setPackages(Arrays.asList("misc.migration.v1_2")); + server = EbeanServerFactory.create(config); + migration.setServer(server); + assertThat(migration.generateMigration()).isEqualTo("1.3"); + assertThat(migration.generateMigration()).isNull(); // subsequent call + + + System.setProperty("ddl.migration.pendingDropsFor", "1.3"); + assertThat(migration.generateMigration()).isEqualTo("1.4__dropsFor_1.3"); + System.clearProperty("ddl.migration.pendingDropsFor"); + assertThat(migration.generateMigration()).isNull(); // subsequent call + + logger.info("end"); + } + +} diff --git a/src/test/java/io/ebean/dbmigration/DbMigrationTest.java b/src/test/java/io/ebean/dbmigration/DbMigrationTest.java index e2e933e44..fe3d446c7 100644 --- a/src/test/java/io/ebean/dbmigration/DbMigrationTest.java +++ b/src/test/java/io/ebean/dbmigration/DbMigrationTest.java @@ -1,31 +1,142 @@ package io.ebean.dbmigration; import io.ebean.BaseTestCase; +import io.ebean.SqlQuery; +import io.ebean.SqlRow; +import io.ebean.SqlUpdate; +import io.ebean.Transaction; +import io.ebean.dbmigration.ddl.DdlRunner; + +import org.junit.Ignore; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; +import java.io.InputStream; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.List; + +import javax.persistence.PersistenceException; + public class DbMigrationTest extends BaseTestCase { private static final Logger logger = LoggerFactory.getLogger(DbMigrationTest.class); - //@Ignore + + private int runScript(boolean expectErrors, String scriptName) throws IOException { + try (InputStream stream = getClass().getResourceAsStream("/dbmigration/migrationtest/" + server().getPluginApi().getDatabasePlatform().getName()+"/" + scriptName); + java.util.Scanner s = new java.util.Scanner(stream)) { + s.useDelimiter("\\A"); + if (s.hasNext()) { + return runScript(expectErrors, s.next(), scriptName); + } + } + return 0; + } + + private int runScript(boolean expectErrors, String content, String scriptName) { + + DdlRunner runner = new DdlRunner(expectErrors, scriptName); + + Transaction transaction = server().createTransaction(); + Connection connection = transaction.getConnection(); + try { + if (expectErrors) { + connection.setAutoCommit(true); + } + int count = runner.runAll(content, connection); + if (expectErrors) { + connection.setAutoCommit(false); + } + transaction.commit(); + return count; + + } catch (SQLException e) { + throw new PersistenceException("Failed to run script", e); + + } finally { + transaction.end(); + } + } @Test - public void writeCurrent() { + public void testRunMigration() throws IOException { + // first clean up previously created objects + runScript(true, "drop table migtest_e_ref;\n","test"); + runScript(true, "drop table migtest_e_basic;\n" + + "drop table migtest_e_history;\n" + + "drop table migtest_e_ref;\n" + + "drop table migtest_e_ref cascade;\n" + + "drop table migtest_e_user;\n" + + "drop table migtest_e_history;\n" + + "drop table migtest_e_history cascade;\n" // pg + + "drop table migtest_e_history_history cascade;\n" // pg + + "drop sequence migtest_e_basic_seq;\n" + + "drop sequence migtest_e_history_seq;\n" + + "drop sequence migtest_e_ref_seq;\n" + + "drop sequence migtest_e_user;\n" + + "drop sequence migtest_e_history;\n" + , "cleanup"); + + + runScript(false, "1.0__initial.sql"); + + SqlUpdate update = server().createSqlUpdate("insert into migtest_e_basic (id, old_boolean, user_id) values (1, :false, 1), (2, :true, 1)"); + update.setParameter("false", false); + update.setParameter("true", true); + + assertThat(server().execute(update)).isEqualTo(2); - logger.info("start"); - DbOffline.asH2(); - DbMigration migration = new DbMigration(); - DbOffline.reset(); + // Run migration + runScript(false, "1.1.sql"); + SqlQuery select = server().createSqlQuery("select * from migtest_e_basic order by id"); + List result = select.findList(); + assertThat(result).hasSize(2); + + SqlRow row = result.get(0); + assertThat(row.keySet()).contains("old_boolean", "old_boolean2"); + + assertThat(row.getInteger("id")).isEqualTo(1); + assertThat(row.getBoolean("old_boolean")).isFalse(); + assertThat(row.getBoolean("new_boolean_field")).isFalse(); // test if update old_boolean -> new_boolean_field works well + + assertThat(row.getString("new_string_field")).isEqualTo("foo'bar"); + assertThat(row.getBoolean("new_boolean_field2")).isTrue(); + assertThat(row.getTimestamp("some_date")).isEqualTo(new Timestamp(100, 0, 1, 0, 0, 0, 0)); // = 2000-01-01T00:00:00 + + row = result.get(1); + assertThat(row.getInteger("id")).isEqualTo(2); + assertThat(row.getBoolean("old_boolean")).isTrue(); + assertThat(row.getBoolean("new_boolean_field")).isTrue(); // test if update old_boolean -> new_boolean_field works well + + assertThat(row.getString("new_string_field")).isEqualTo("foo'bar"); + assertThat(row.getBoolean("new_boolean_field2")).isTrue(); + assertThat(row.getTimestamp("some_date")).isEqualTo(new Timestamp(100, 0, 1, 0, 0, 0, 0)); // = 2000-01-01T00:00:00 - //migration.writeCurrent(); + // Run migration & drops + runScript(false, "1.2__dropsFor_1.1.sql"); - assertThat(DbOffline.isSet()).isFalse(); - - logger.info("end"); + + select = server().createSqlQuery("select * from migtest_e_basic order by id"); + result = select.findList(); + assertThat(result).hasSize(2); + row = result.get(0); + assertThat(row.keySet()).doesNotContain("old_boolean", "old_boolean2"); + + runScript(false, "1.3.sql"); + runScript(false, "1.4__dropsFor_1.3.sql"); + + // now DB structure shoud be the same as v1_0 + select = server().createSqlQuery("select * from migtest_e_basic order by id"); + result = select.findList(); + assertThat(result).hasSize(2); + row = result.get(0); + assertThat(row.keySet()).contains("old_boolean", "old_boolean2"); } } diff --git a/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java b/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java index 8e04296e4..7d98415cf 100644 --- a/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java +++ b/src/test/java/io/ebean/dbmigration/ddlgeneration/BaseDdlHandlerTest.java @@ -48,7 +48,8 @@ public class BaseDdlHandlerTest extends BaseTestCase { DdlWrite write = new DdlWrite(); h2Handler().generate(write, Helper.getAlterTableAddColumnWithCheckConstraint()); - assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column status integer constraint ck_ordering_status check ( status in (0,1));\n\n"); + assertThat(write.apply().getBuffer()).isEqualTo("alter table foo add column status integer;\n" + + "alter table foo add constraint ck_ordering_status check ( status in (0,1));\n\n"); } /** 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 17c2eea75..7b9439974 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 @@ -157,7 +157,7 @@ public class PlatformDdl_AlterColumnTest { assertEquals("alter table mytab alter acol set default 'hi'", sql); sql = sqlServerDdl.alterColumnDefaultValue("mytab", "acol", "'hi'"); - assertEquals("alter table mytab add default 'hi' for acol", sql); + assertEquals("alter table mytab add constraint df_mytab_acol default 'hi' for acol", sql); } @Test @@ -176,7 +176,7 @@ public class PlatformDdl_AlterColumnTest { assertEquals("alter table mytab alter acol drop default", sql); sql = sqlServerDdl.alterColumnDefaultValue("mytab", "acol", "DROP DEFAULT"); - assertTrue(sql, sql.startsWith("-- alter")); + assertEquals("alter table mytab drop constraint df_mytab_acol", sql); } } diff --git a/src/test/java/misc/migration/v1_0/EBasic.java b/src/test/java/misc/migration/v1_0/EBasic.java new file mode 100644 index 000000000..5d7842b85 --- /dev/null +++ b/src/test/java/misc/migration/v1_0/EBasic.java @@ -0,0 +1,116 @@ +package misc.migration.v1_0; + +import io.ebean.annotation.EnumValue; +import io.ebean.annotation.Index; +import io.ebean.annotation.NotNull; +import misc.migration.v1_1.EUser; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import java.sql.Timestamp; + +@Entity +@Table(name = "migtest_e_basic") +public class EBasic { + + public enum Status { + @EnumValue("N") + NEW, + + @EnumValue("A") + ACTIVE, + + @EnumValue("I") + INACTIVE, + } + + @Id + Integer id; + + Status status; + + String name; + + String description; + + Timestamp someDate; + + boolean old_boolean; + + Boolean old_boolean2; + + @ManyToOne + ERef eref; + + + // test add & remove indices + @Index + String indextest1; + + @Index(unique = true) + String indextest2; + + String indextest3; + + String indextest4; + + @Index(unique = false) + String indextest5; + + @Index(unique = true) + String indextest6; + + @NotNull + int user_id; + + public EBasic() { + + } + + public EBasic(String name) { + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Timestamp getSomeDate() { + return someDate; + } + + public void setSomeDate(Timestamp someDate) { + this.someDate = someDate; + } + +} diff --git a/src/test/java/misc/migration/v1_0/EHistory.java b/src/test/java/misc/migration/v1_0/EHistory.java new file mode 100644 index 000000000..fe0bcdfe9 --- /dev/null +++ b/src/test/java/misc/migration/v1_0/EHistory.java @@ -0,0 +1,17 @@ +package misc.migration.v1_0; + + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "migtest_e_history") +public class EHistory { + + @Id + Integer id; + + + String testString; +} diff --git a/src/test/java/misc/migration/v1_0/ERef.java b/src/test/java/misc/migration/v1_0/ERef.java new file mode 100644 index 000000000..c96f43d03 --- /dev/null +++ b/src/test/java/misc/migration/v1_0/ERef.java @@ -0,0 +1,19 @@ +package misc.migration.v1_0; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "migtest_e_ref") +public class ERef { + + @Id + Integer id; + + @OneToMany + List basics; +} diff --git a/src/test/java/misc/migration/v1_1/EBasic.java b/src/test/java/misc/migration/v1_1/EBasic.java new file mode 100644 index 000000000..26d708ac1 --- /dev/null +++ b/src/test/java/misc/migration/v1_1/EBasic.java @@ -0,0 +1,162 @@ +package misc.migration.v1_1; + +import io.ebean.Platform; +import io.ebean.annotation.DbDefault; +import io.ebean.annotation.DbMigration; +import io.ebean.annotation.EnumValue; +import io.ebean.annotation.Index; +import io.ebean.annotation.NotNull; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import java.sql.Timestamp; + +@Entity +@Table(name = "migtest_e_basic") +public class EBasic { + + public enum Status { + @EnumValue("N") + NEW, + + @EnumValue("A") + ACTIVE, + + @EnumValue("I") + INACTIVE, + + @EnumValue("?") + DONT_KNOW, + } + + public enum Progress { + @EnumValue("0") + START, + + @EnumValue("1") + RUN, + + @EnumValue("2") + END + } + + @Id + Integer id; + + @NotNull + @DbDefault("A") + Status status; + + @Index(unique = true) + String name; + + + @DbMigration(preAlter = "-- rename all collisions") + @Column(unique = true) + String description; + + @NotNull + @DbDefault("2000-01-01T00:00:00") + Timestamp someDate; + + @NotNull + @DbDefault("foo'bar") + String newStringField; + + @NotNull + @DbDefault("true") + @DbMigration(postAdd = "update ${table} set ${column} = old_boolean") + Boolean newBooleanField; + + @NotNull + @DbDefault("true") + boolean newBooleanField2; + + String indextest1; + + String indextest2; + + @Index + String indextest3; + + @Index(unique = true) + String indextest4; + + @Index(unique = true) + String indextest5; + + @Index(unique = false) + String indextest6; + + @NotNull + @DbDefault("0") + Progress progress; + + @DbDefault("42") + int newInteger; + + @NotNull + @ManyToOne + @DbMigration(preAlter= "insert into migtest_e_user (id) select distinct user_id from migtest_e_basic") // ensure all users exist + EUser user; + + public EBasic() { + + } + + public EBasic(String name) { + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Timestamp getSomeDate() { + return someDate; + } + + public void setSomeDate(Timestamp someDate) { + this.someDate = someDate; + } + + public String getNewStringField() { + return newStringField; + } + + public void setNewStringField(String newStringField) { + this.newStringField = newStringField; + } +} diff --git a/src/test/java/misc/migration/v1_1/EHistory.java b/src/test/java/misc/migration/v1_1/EHistory.java new file mode 100644 index 000000000..6b29bc2a3 --- /dev/null +++ b/src/test/java/misc/migration/v1_1/EHistory.java @@ -0,0 +1,26 @@ +package misc.migration.v1_1; + + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +import io.ebean.Platform; +import io.ebean.annotation.DbComment; +import io.ebean.annotation.DbMigration; +import io.ebean.annotation.History; + +@Entity +@Table(name = "migtest_e_history") +@History +@DbComment("We have history now") +public class EHistory { + + @Id + Integer id; + + @DbComment("Column altered to long now") + @DbMigration(platforms = Platform.POSTGRES, + preAlter = "alter table ${table} alter column ${column} TYPE bigint USING (${column}::integer)") + Long testString; +} diff --git a/src/test/java/misc/migration/v1_1/EUser.java b/src/test/java/misc/migration/v1_1/EUser.java new file mode 100644 index 000000000..42b901033 --- /dev/null +++ b/src/test/java/misc/migration/v1_1/EUser.java @@ -0,0 +1,13 @@ +package misc.migration.v1_1; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "migtest_e_user") +public class EUser { + + @Id + Integer id; +} \ No newline at end of file diff --git a/src/test/java/misc/migration/v1_2/EBasic.java b/src/test/java/misc/migration/v1_2/EBasic.java new file mode 100644 index 000000000..3dc070818 --- /dev/null +++ b/src/test/java/misc/migration/v1_2/EBasic.java @@ -0,0 +1,118 @@ +package misc.migration.v1_2; + +import io.ebean.annotation.DbDefault; +import io.ebean.annotation.EnumValue; +import io.ebean.annotation.Index; +import io.ebean.annotation.NotNull; +import misc.migration.v1_1.EUser; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import java.sql.Timestamp; + +@Entity +@Table(name = "migtest_e_basic") +public class EBasic { + + public enum Status { + @EnumValue("N") + NEW, + + @EnumValue("A") + ACTIVE, + + @EnumValue("I") + INACTIVE, + } + + @Id + Integer id; + + Status status; + + String name; + + String description; + + Timestamp someDate; + + boolean old_boolean; + + Boolean old_boolean2; + + @ManyToOne + ERef eref; + + + // test add & remove indices + @Index + String indextest1; + + @Index(unique = true) + String indextest2; + + String indextest3; + + String indextest4; + + @Index(unique = false) + String indextest5; + + @Index(unique = true) + String indextest6; + + @NotNull + @DbDefault("23") + int user_id; + + public EBasic() { + + } + + public EBasic(String name) { + this.name = name; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Timestamp getSomeDate() { + return someDate; + } + + public void setSomeDate(Timestamp someDate) { + this.someDate = someDate; + } + +} diff --git a/src/test/java/misc/migration/v1_2/EHistory.java b/src/test/java/misc/migration/v1_2/EHistory.java new file mode 100644 index 000000000..0e166625c --- /dev/null +++ b/src/test/java/misc/migration/v1_2/EHistory.java @@ -0,0 +1,17 @@ +package misc.migration.v1_2; + + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "migtest_e_history") +public class EHistory { + + @Id + Integer id; + + + Long testString; // keep it as long as history prevents altering +} diff --git a/src/test/java/misc/migration/v1_2/ERef.java b/src/test/java/misc/migration/v1_2/ERef.java new file mode 100644 index 000000000..aa22e9034 --- /dev/null +++ b/src/test/java/misc/migration/v1_2/ERef.java @@ -0,0 +1,19 @@ +package misc.migration.v1_2; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +@Entity +@Table(name = "migtest_e_ref") +public class ERef { + + @Id + Integer id; + + @OneToMany + List basics; +} diff --git a/src/test/resources/dbmigration/migrationtest/db2/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/db2/1.0__initial.sql new file mode 100644 index 000000000..eb452c747 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id integer generated by default as identity not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date timestamp, + old_boolean boolean default false not null, + old_boolean2 boolean, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint pk_migtest_e_basic primary key (id) +); +-- NOT SUPPORTED alter table migtest_e_basic add constraint uq_migtest_e_basic_indextest2 unique (indextest2); +-- NOT SUPPORTED alter table migtest_e_basic add constraint uq_migtest_e_basic_indextest6 unique (indextest6); + +create table migtest_e_history ( + id integer generated by default as identity not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer generated by default as identity not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/db2/1.1.sql b/src/test/resources/dbmigration/migrationtest/db2/1.1.sql new file mode 100644 index 000000000..2a11c8390 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/1.1.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_user ( + id integer generated by default as identity not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status set default 'A'; +alter table migtest_e_basic alter column status set not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +-- NOT SUPPORTED alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic alter column some_date set not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict; +alter table migtest_e_basic alter column user_id set null; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field boolean not null default true; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 boolean not null default true; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history alter column test_string bigint; +comment on table migtest_e_history is 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index ix_migtest_e_basic_indextest1; +drop index ix_migtest_e_basic_indextest5; diff --git a/src/test/resources/dbmigration/migrationtest/db2/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/db2/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..d0243323d --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/db2/1.3.sql b/src/test/resources/dbmigration/migrationtest/db2/1.3.sql new file mode 100644 index 000000000..d3cc83024 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/1.3.sql @@ -0,0 +1,30 @@ +-- apply changes +create table migtest_e_ref ( + id integer generated by default as identity not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status drop default; +alter table migtest_e_basic alter column status set null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic alter column some_date drop default; +alter table migtest_e_basic alter column some_date set null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop constraint fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter column user_id set default 23; +alter table migtest_e_basic alter column user_id set not null; +alter table migtest_e_basic add column old_boolean boolean not null default false; +alter table migtest_e_basic add column old_boolean2 boolean; +alter table migtest_e_basic add column eref_id integer; + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index ix_migtest_e_basic_indextest3; +drop index ix_migtest_e_basic_indextest6; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/db2/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/db2/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..6d20a02da --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/1.4__dropsFor_1.3.sql @@ -0,0 +1,12 @@ +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table migtest_e_user; diff --git a/src/test/resources/dbmigration/migrationtest/db2/R__order_views.sql b/src/test/resources/dbmigration/migrationtest/db2/R__order_views.sql new file mode 100644 index 000000000..c22cb7533 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/db2/R__order_views.sql @@ -0,0 +1,8 @@ + + + create or replace view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/h2/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/h2/1.0__initial.sql new file mode 100644 index 000000000..a56745884 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id integer auto_increment not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date timestamp, + old_boolean boolean default false not null, + old_boolean2 boolean, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id) +); + +create table migtest_e_history ( + id integer auto_increment not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer auto_increment not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/h2/1.1.sql b/src/test/resources/dbmigration/migrationtest/h2/1.1.sql new file mode 100644 index 000000000..88e60af97 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/1.1.sql @@ -0,0 +1,50 @@ +-- apply changes +create table migtest_e_user ( + id integer auto_increment not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status set default 'A'; +alter table migtest_e_basic alter column status set not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic alter column some_date set not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict; +alter table migtest_e_basic alter column user_id set null; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field boolean not null default true; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 boolean not null default true; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history alter column test_string bigint; +comment on table migtest_e_history is 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index if exists ix_migtest_e_basic_indextest1; +drop index if exists ix_migtest_e_basic_indextest5; +alter table migtest_e_history add column sys_period_start datetime(6) default now(6); +alter table migtest_e_history add column sys_period_end datetime(6); +create table migtest_e_history_history( + id integer, + test_string bigint, + sys_period_start datetime(6), + sys_period_end datetime(6) +); +create view migtest_e_history_with_history as select * from migtest_e_history union all select * from migtest_e_history_history; + +create trigger migtest_e_history_history_upd before update,delete on migtest_e_history for each row call "io.ebean.config.dbplatform.h2.H2HistoryTrigger"; diff --git a/src/test/resources/dbmigration/migrationtest/h2/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/h2/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..05a3f449e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table if exists migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/h2/1.3.sql b/src/test/resources/dbmigration/migrationtest/h2/1.3.sql new file mode 100644 index 000000000..574b9a362 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/1.3.sql @@ -0,0 +1,30 @@ +-- apply changes +create table migtest_e_ref ( + id integer auto_increment not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status drop default; +alter table migtest_e_basic alter column status set null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic alter column some_date drop default; +alter table migtest_e_basic alter column some_date set null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter column user_id set default 23; +alter table migtest_e_basic alter column user_id set not null; +alter table migtest_e_basic add column old_boolean boolean not null default false; +alter table migtest_e_basic add column old_boolean2 boolean; +alter table migtest_e_basic add column eref_id integer; + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index if exists ix_migtest_e_basic_indextest3; +drop index if exists ix_migtest_e_basic_indextest6; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/h2/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/h2/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..1179896ec --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/1.4__dropsFor_1.3.sql @@ -0,0 +1,20 @@ +-- drop dependencies +drop trigger migtest_e_history_history_upd; +drop view migtest_e_history_with_history; +alter table migtest_e_history drop column sys_period_start; +alter table migtest_e_history drop column sys_period_end; +drop table migtest_e_history_history; + + +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table if exists migtest_e_user; diff --git a/src/test/resources/dbmigration/migrationtest/h2/R__multi_comments.sql b/src/test/resources/dbmigration/migrationtest/h2/R__multi_comments.sql new file mode 100644 index 000000000..0ede0c9eb --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/R__multi_comments.sql @@ -0,0 +1,3 @@ + + -- h2 and postgres script + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/h2/R__order_views.sql b/src/test/resources/dbmigration/migrationtest/h2/R__order_views.sql new file mode 100644 index 000000000..c22cb7533 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/h2/R__order_views.sql @@ -0,0 +1,8 @@ + + + create or replace view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/1.0__initial.sql new file mode 100644 index 000000000..6eb8ba786 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id integer generated by default as identity (start with 1) not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date timestamp, + old_boolean boolean default false not null, + old_boolean2 boolean, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id) +); + +create table migtest_e_history ( + id integer generated by default as identity (start with 1) not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer generated by default as identity (start with 1) not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/1.1.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/1.1.sql new file mode 100644 index 000000000..1d17c55a6 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/1.1.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_user ( + id integer generated by default as identity (start with 1) not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status set default 'A'; +alter table migtest_e_basic alter column status set not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic alter column some_date set not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict; +alter table migtest_e_basic alter column user_id set null; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field boolean not null default true; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 boolean not null default true; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history alter column test_string bigint; +comment on table migtest_e_history is 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index if exists ix_migtest_e_basic_indextest1; +drop index if exists ix_migtest_e_basic_indextest5; diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..05a3f449e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table if exists migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/1.3.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/1.3.sql new file mode 100644 index 000000000..cca1c04e6 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/1.3.sql @@ -0,0 +1,30 @@ +-- apply changes +create table migtest_e_ref ( + id integer generated by default as identity (start with 1) not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status drop default; +alter table migtest_e_basic alter column status set null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic alter column some_date drop default; +alter table migtest_e_basic alter column some_date set null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter column user_id set default 23; +alter table migtest_e_basic alter column user_id set not null; +alter table migtest_e_basic add column old_boolean boolean not null default false; +alter table migtest_e_basic add column old_boolean2 boolean; +alter table migtest_e_basic add column eref_id integer; + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index if exists ix_migtest_e_basic_indextest3; +drop index if exists ix_migtest_e_basic_indextest6; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..203511771 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/1.4__dropsFor_1.3.sql @@ -0,0 +1,12 @@ +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table if exists migtest_e_user; diff --git a/src/test/resources/dbmigration/migrationtest/hsqldb/R__order_views_hsqldb.sql b/src/test/resources/dbmigration/migrationtest/hsqldb/R__order_views_hsqldb.sql new file mode 100644 index 000000000..5f7ba1784 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/hsqldb/R__order_views_hsqldb.sql @@ -0,0 +1,8 @@ + + drop view order_agg_vw if exists ; + create view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/model/1.0__initial.model.xml b/src/test/resources/dbmigration/migrationtest/model/1.0__initial.model.xml new file mode 100644 index 000000000..d57e29028 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/model/1.0__initial.model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/model/1.1.model.xml b/src/test/resources/dbmigration/migrationtest/model/1.1.model.xml new file mode 100644 index 000000000..f8773a5bb --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/model/1.1.model.xml @@ -0,0 +1,41 @@ + + + + + + + -- rename all collisions + + + + insert into migtest_e_user (id) select distinct user_id from migtest_e_basic + + + + + update ${table} set ${column} = old_boolean + + + + + + + + alter table ${table} alter column ${column} TYPE bigint USING (${column}::integer) + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/model/1.2__dropsFor_1.1.model.xml b/src/test/resources/dbmigration/migrationtest/model/1.2__dropsFor_1.1.model.xml new file mode 100644 index 000000000..cf5d7dda9 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/model/1.2__dropsFor_1.1.model.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/model/1.3.model.xml b/src/test/resources/dbmigration/migrationtest/model/1.3.model.xml new file mode 100644 index 000000000..7e66df907 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/model/1.3.model.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/model/1.4__dropsFor_1.3.model.xml b/src/test/resources/dbmigration/migrationtest/model/1.4__dropsFor_1.3.model.xml new file mode 100644 index 000000000..398853857 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/model/1.4__dropsFor_1.3.model.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/mysql/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/mysql/1.0__initial.sql new file mode 100644 index 000000000..0b3ef8584 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id integer auto_increment not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date datetime(6), + old_boolean tinyint(1) default 0 not null, + old_boolean2 tinyint(1) default 0, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id) +); + +create table migtest_e_history ( + id integer auto_increment not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer auto_increment not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/mysql/1.1.sql b/src/test/resources/dbmigration/migrationtest/mysql/1.1.sql new file mode 100644 index 000000000..ede5c47ff --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/1.1.sql @@ -0,0 +1,57 @@ +-- apply changes +create table migtest_e_user ( + id integer auto_increment not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic alter status set default 'A'; +alter table migtest_e_basic modify status varchar(1) not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic modify some_date datetime(6) not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict; +alter table migtest_e_basic modify user_id integer; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field tinyint(1) default 0 not null; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 tinyint(1) default 0 not null; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history modify test_string bigint; +alter table migtest_e_history comment = 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index ix_migtest_e_basic_indextest1 on migtest_e_basic; +drop index ix_migtest_e_basic_indextest5 on migtest_e_basic; +alter table migtest_e_history add column sys_period_start datetime(6) default now(6); +alter table migtest_e_history add column sys_period_end datetime(6); +create table migtest_e_history_history( + id integer, + test_string bigint, + sys_period_start datetime(6), + sys_period_end datetime(6) +); +create view migtest_e_history_with_history as select * from migtest_e_history union all select * from migtest_e_history_history; + +delimiter $$ +create trigger migtest_e_history_history_upd before update on migtest_e_history for each row begin + insert into migtest_e_history_history (sys_period_start,sys_period_end,id, test_string) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string); + set NEW.sys_period_start = now(6); +end$$ +delimiter $$ +create trigger migtest_e_history_history_del before delete on migtest_e_history for each row begin + insert into migtest_e_history_history (sys_period_start,sys_period_end,id, test_string) values (OLD.sys_period_start, now(6),OLD.id, OLD.test_string); +end$$ diff --git a/src/test/resources/dbmigration/migrationtest/mysql/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/mysql/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..05a3f449e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table if exists migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/mysql/1.3.sql b/src/test/resources/dbmigration/migrationtest/mysql/1.3.sql new file mode 100644 index 000000000..58f7fef6e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/1.3.sql @@ -0,0 +1,27 @@ +-- apply changes +create table migtest_e_ref ( + id integer auto_increment not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic alter status drop default; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop index uq_migtest_e_basic_description; +alter table migtest_e_basic alter some_date drop default; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop foreign key fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter user_id set default 23; +alter table migtest_e_basic modify user_id integer not null; +alter table migtest_e_basic add column old_boolean tinyint(1) default 0 not null; +alter table migtest_e_basic add column old_boolean2 tinyint(1) default 0; +alter table migtest_e_basic add column eref_id integer; + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index ix_migtest_e_basic_indextest3 on migtest_e_basic; +drop index ix_migtest_e_basic_indextest6 on migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/mysql/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/mysql/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..50d0d6bb0 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/1.4__dropsFor_1.3.sql @@ -0,0 +1,21 @@ +-- drop dependencies +drop trigger migtest_e_history_history_upd; +drop trigger migtest_e_history_history_del; +drop view migtest_e_history_with_history; +alter table migtest_e_history drop column sys_period_start; +alter table migtest_e_history drop column sys_period_end; +drop table migtest_e_history_history; + + +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table if exists migtest_e_user; diff --git a/src/test/resources/dbmigration/migrationtest/mysql/R__order_views.sql b/src/test/resources/dbmigration/migrationtest/mysql/R__order_views.sql new file mode 100644 index 000000000..c22cb7533 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/mysql/R__order_views.sql @@ -0,0 +1,8 @@ + + + create or replace view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/oracle/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/oracle/1.0__initial.sql new file mode 100644 index 000000000..42144bdeb --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/1.0__initial.sql @@ -0,0 +1,42 @@ +-- apply changes +create table migtest_e_basic ( + id number(10) not null, + status varchar2(1), + name varchar2(255), + description varchar2(255), + some_date timestamp, + old_boolean number(1) default 0 not null, + old_boolean2 number(1) default 0, + eref_id number(10), + indextest1 varchar2(255), + indextest2 varchar2(255), + indextest3 varchar2(255), + indextest4 varchar2(255), + indextest5 varchar2(255), + indextest6 varchar2(255), + user_id number(10) not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id) +); +create sequence migtest_e_basic_seq; + +create table migtest_e_history ( + id number(10) not null, + test_string varchar2(255), + constraint pk_migtest_e_history primary key (id) +); +create sequence migtest_e_history_seq; + +create table migtest_e_ref ( + id number(10) not null, + constraint pk_migtest_e_ref primary key (id) +); +create sequence migtest_e_ref_seq; + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id); +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/oracle/1.1.sql b/src/test/resources/dbmigration/migrationtest/oracle/1.1.sql new file mode 100644 index 000000000..1dd8204ce --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/1.1.sql @@ -0,0 +1,40 @@ +-- apply changes +create table migtest_e_user ( + id number(10) not null, + constraint pk_migtest_e_user primary key (id) +); +create sequence migtest_e_user_seq; + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic modify status default 'A'; +alter table migtest_e_basic modify status not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic modify some_date default '2000-01-01T00:00:00'; +alter table migtest_e_basic modify some_date not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id); +alter table migtest_e_basic modify user_id null; +alter table migtest_e_basic add column new_string_field varchar2(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field number(1) default 0 not null; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 number(1) default 0 not null; +alter table migtest_e_basic add column progress number(10) not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer number(10) not null default 42; + +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history modify test_string number(19); +comment on table migtest_e_history is 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index ix_migtest_e_basic_indextest1; +drop index ix_migtest_e_basic_indextest5; diff --git a/src/test/resources/dbmigration/migrationtest/oracle/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/oracle/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..212351c21 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table migtest_e_ref cascade constraints purge; diff --git a/src/test/resources/dbmigration/migrationtest/oracle/1.3.sql b/src/test/resources/dbmigration/migrationtest/oracle/1.3.sql new file mode 100644 index 000000000..db710a973 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/1.3.sql @@ -0,0 +1,31 @@ +-- apply changes +create table migtest_e_ref ( + id number(10) not null, + constraint pk_migtest_e_ref primary key (id) +); +create sequence migtest_e_ref_seq; + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic modify status drop default; +alter table migtest_e_basic modify status null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic modify some_date drop default; +alter table migtest_e_basic modify some_date null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop constraint fk_migtest_e_basic_user_id; +alter table migtest_e_basic modify user_id default 23; +alter table migtest_e_basic modify user_id not null; +alter table migtest_e_basic add column old_boolean number(1) default 0 not null; +alter table migtest_e_basic add column old_boolean2 number(1) default 0; +alter table migtest_e_basic add column eref_id number(10); + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index ix_migtest_e_basic_indextest3; +drop index ix_migtest_e_basic_indextest6; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id); +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/oracle/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/oracle/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..119695b0e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/1.4__dropsFor_1.3.sql @@ -0,0 +1,12 @@ +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table migtest_e_user cascade constraints purge; diff --git a/src/test/resources/dbmigration/migrationtest/oracle/R__oracle_only_views.sql b/src/test/resources/dbmigration/migrationtest/oracle/R__oracle_only_views.sql new file mode 100644 index 000000000..daaddc89c --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/R__oracle_only_views.sql @@ -0,0 +1,3 @@ + + -- oracle only script + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/oracle/R__order_views.sql b/src/test/resources/dbmigration/migrationtest/oracle/R__order_views.sql new file mode 100644 index 000000000..c22cb7533 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/oracle/R__order_views.sql @@ -0,0 +1,8 @@ + + + create or replace view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/postgres/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/postgres/1.0__initial.sql new file mode 100644 index 000000000..1e2cc3b18 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id serial not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date timestamptz, + old_boolean boolean default false not null, + old_boolean2 boolean, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id) +); + +create table migtest_e_history ( + id serial not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id serial not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/postgres/1.1.sql b/src/test/resources/dbmigration/migrationtest/postgres/1.1.sql new file mode 100644 index 000000000..549e99d53 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/1.1.sql @@ -0,0 +1,62 @@ +-- apply changes +create table migtest_e_user ( + id serial not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status set default 'A'; +alter table migtest_e_basic alter column status set not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic alter column some_date set not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id) on delete restrict on update restrict; +alter table migtest_e_basic alter column user_id drop not null; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field boolean not null default true; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 boolean not null default true; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + + +alter table migtest_e_history alter column test_string TYPE bigint USING (test_string::integer); +comment on column migtest_e_history.test_string is 'Column altered to long now'; +alter table migtest_e_history alter column test_string type bigint; +comment on table migtest_e_history is 'We have history now'; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index if exists ix_migtest_e_basic_indextest1; +drop index if exists ix_migtest_e_basic_indextest5; +alter table migtest_e_history add column sys_period tstzrange not null default tstzrange(current_timestamp, null); +create table migtest_e_history_history(like migtest_e_history); +create view migtest_e_history_with_history as select * from migtest_e_history union all select * from migtest_e_history_history; + +create or replace function migtest_e_history_history_version() returns trigger as $$ +begin + if (TG_OP = 'UPDATE') then + insert into migtest_e_history_history (sys_period,id, test_string) values (tstzrange(lower(OLD.sys_period), current_timestamp), OLD.id, OLD.test_string); + NEW.sys_period = tstzrange(current_timestamp,null); + return new; + elsif (TG_OP = 'DELETE') then + insert into migtest_e_history_history (sys_period,id, test_string) values (tstzrange(lower(OLD.sys_period), current_timestamp), OLD.id, OLD.test_string); + return old; + end if; +end; +$$ LANGUAGE plpgsql; + +create trigger migtest_e_history_history_upd + before update or delete on migtest_e_history + for each row execute procedure migtest_e_history_history_version(); + diff --git a/src/test/resources/dbmigration/migrationtest/postgres/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/postgres/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..3f4a147db --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table if exists migtest_e_ref cascade; diff --git a/src/test/resources/dbmigration/migrationtest/postgres/1.3.sql b/src/test/resources/dbmigration/migrationtest/postgres/1.3.sql new file mode 100644 index 000000000..46835021a --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/1.3.sql @@ -0,0 +1,30 @@ +-- apply changes +create table migtest_e_ref ( + id serial not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status drop default; +alter table migtest_e_basic alter column status drop not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic alter column some_date drop default; +alter table migtest_e_basic alter column some_date drop not null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table if exists migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter column user_id set default 23; +alter table migtest_e_basic alter column user_id set not null; +alter table migtest_e_basic add column old_boolean boolean not null default false; +alter table migtest_e_basic add column old_boolean2 boolean; +alter table migtest_e_basic add column eref_id integer; + +comment on column migtest_e_history.test_string is 'DROP COMMENT'; +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index if exists ix_migtest_e_basic_indextest3; +drop index if exists ix_migtest_e_basic_indextest6; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/postgres/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/postgres/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..245eee0f5 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/1.4__dropsFor_1.3.sql @@ -0,0 +1,21 @@ +-- drop dependencies +drop trigger if exists migtest_e_history_history_upd on migtest_e_history cascade; +drop function if exists migtest_e_history_history_version(); + +drop view migtest_e_history_with_history; +alter table migtest_e_history drop column sys_period; +drop table migtest_e_history_history; + + +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table if exists migtest_e_user cascade; diff --git a/src/test/resources/dbmigration/migrationtest/postgres/R__multi_comments.sql b/src/test/resources/dbmigration/migrationtest/postgres/R__multi_comments.sql new file mode 100644 index 000000000..0ede0c9eb --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/R__multi_comments.sql @@ -0,0 +1,3 @@ + + -- h2 and postgres script + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/postgres/R__order_views.sql b/src/test/resources/dbmigration/migrationtest/postgres/R__order_views.sql new file mode 100644 index 000000000..c22cb7533 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/R__order_views.sql @@ -0,0 +1,8 @@ + + + create or replace view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/postgres/R__pg_indexes.sql b/src/test/resources/dbmigration/migrationtest/postgres/R__pg_indexes.sql new file mode 100644 index 000000000..fa0bab998 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/postgres/R__pg_indexes.sql @@ -0,0 +1,4 @@ + + -- postgres specific indexes + create index ix_ebasic_jmjb_gin2 on ebasic_json_map_json_b using gin(content jsonb_path_ops); + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/sqlite/1.0__initial.sql new file mode 100644 index 000000000..02c62cdff --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/1.0__initial.sql @@ -0,0 +1,37 @@ +-- apply changes +create table migtest_e_basic ( + id integer not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date timestamp, + old_boolean int default 0 not null, + old_boolean2 int default 0, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint uq_migtest_e_basic_indextest2 unique (indextest2), + constraint uq_migtest_e_basic_indextest6 unique (indextest6), + constraint pk_migtest_e_basic primary key (id), + foreign key (eref_id) references migtest_e_ref (id) on delete restrict on update restrict +); + +create table migtest_e_history ( + id integer not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/1.1.sql b/src/test/resources/dbmigration/migrationtest/sqlite/1.1.sql new file mode 100644 index 000000000..c7ee1643b --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/1.1.sql @@ -0,0 +1,36 @@ +-- apply changes +create table migtest_e_user ( + id integer not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status set default 'A'; +alter table migtest_e_basic alter column status set not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +alter table migtest_e_basic add constraint uq_migtest_e_basic_description unique (description); + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic alter column some_date set default '2000-01-01T00:00:00'; +alter table migtest_e_basic alter column some_date set not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic alter column user_id set null; +alter table migtest_e_basic add column new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add column new_boolean_field int default 0 not null; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add column new_boolean_field2 int default 0 not null; +alter table migtest_e_basic add column progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add column new_integer integer not null default 42; + +alter table migtest_e_history alter column test_string integer; +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +drop index if exists ix_migtest_e_basic_indextest1; +drop index if exists ix_migtest_e_basic_indextest5; diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/sqlite/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..05a3f449e --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +drop table if exists migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/1.3.sql b/src/test/resources/dbmigration/migrationtest/sqlite/1.3.sql new file mode 100644 index 000000000..5509970df --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/1.3.sql @@ -0,0 +1,28 @@ +-- apply changes +create table migtest_e_ref ( + id integer not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic alter column status drop default; +alter table migtest_e_basic alter column status set null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic alter column some_date drop default; +alter table migtest_e_basic alter column some_date set null; + +update migtest_e_basic set user_id = 23 where user_id is null; +alter table migtest_e_basic drop constraint if exists fk_migtest_e_basic_user_id; +alter table migtest_e_basic alter column user_id set default 23; +alter table migtest_e_basic alter column user_id set not null; +alter table migtest_e_basic add column old_boolean int default 0 not null; +alter table migtest_e_basic add column old_boolean2 int default 0; +alter table migtest_e_basic add column eref_id integer; + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +drop index if exists ix_migtest_e_basic_indextest3; +drop index if exists ix_migtest_e_basic_indextest6; +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/sqlite/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..203511771 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/1.4__dropsFor_1.3.sql @@ -0,0 +1,12 @@ +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +drop table if exists migtest_e_user; diff --git a/src/test/resources/dbmigration/migrationtest/sqlite/R__order_views_sqlite.sql b/src/test/resources/dbmigration/migrationtest/sqlite/R__order_views_sqlite.sql new file mode 100644 index 000000000..e078ac639 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlite/R__order_views_sqlite.sql @@ -0,0 +1,9 @@ + + drop view if exists order_agg_vw; + create view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + + \ No newline at end of file diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/1.0__initial.sql new file mode 100644 index 000000000..ce13b6a8f --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/1.0__initial.sql @@ -0,0 +1,39 @@ +-- apply changes +create table migtest_e_basic ( + id integer identity(1,1) not null, + status varchar(1), + name varchar(255), + description varchar(255), + some_date datetime2, + old_boolean bit default 0 not null, + old_boolean2 bit default 0, + eref_id integer, + indextest1 varchar(255), + indextest2 varchar(255), + indextest3 varchar(255), + indextest4 varchar(255), + indextest5 varchar(255), + indextest6 varchar(255), + user_id integer not null, + constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), + constraint pk_migtest_e_basic primary key (id) +); +create unique nonclustered index uq_migtest_e_basic_indextest2 on migtest_e_basic(indextest2) where indextest2 is not null; +create unique nonclustered index uq_migtest_e_basic_indextest6 on migtest_e_basic(indextest6) where indextest6 is not null; + +create table migtest_e_history ( + id integer identity(1,1) not null, + test_string varchar(255), + constraint pk_migtest_e_history primary key (id) +); + +create table migtest_e_ref ( + id integer identity(1,1) not null, + constraint pk_migtest_e_ref primary key (id) +); + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id); +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/1.1.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/1.1.sql new file mode 100644 index 000000000..8b8465ea1 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/1.1.sql @@ -0,0 +1,42 @@ +-- apply changes +create table migtest_e_user ( + id integer identity(1,1) not null, + constraint pk_migtest_e_user primary key (id) +); + + +update migtest_e_basic set status = 'A' where status is null; +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic add constraint df_migtest_e_basic_status default 'A' for status; +alter table migtest_e_basic alter column status varchar(1) not null; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I','?')); + +-- rename all collisions; +create unique nonclustered index uq_migtest_e_basic_description on migtest_e_basic(description) where description is not null; + +update migtest_e_basic set some_date = '2000-01-01T00:00:00' where some_date is null; +alter table migtest_e_basic add constraint df_migtest_e_basic_some_date default '2000-01-01T00:00:00' for some_date; +alter table migtest_e_basic alter column some_date datetime2 not null; + +insert into migtest_e_user (id) select distinct user_id from migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id); +alter table migtest_e_basic alter column user_id integer; +alter table migtest_e_basic add new_string_field varchar(255) not null default 'foo''bar'; +alter table migtest_e_basic add new_boolean_field bit default 0 not null; +update migtest_e_basic set new_boolean_field = old_boolean; + +alter table migtest_e_basic add new_boolean_field2 bit default 0 not null; +alter table migtest_e_basic add progress integer not null default 0; +alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2)); +alter table migtest_e_basic add new_integer integer not null default 42; + +alter table migtest_e_history alter column test_string numeric(19); +create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3); +create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6); +IF EXISTS (SELECT name FROM sys.indexes WHERE object_id = OBJECT_ID('migtest_e_basic','U') AND name = 'ix_migtest_e_basic_indextest1') drop index ix_migtest_e_basic_indextest1 ON migtest_e_basic; +IF EXISTS (SELECT name FROM sys.indexes WHERE object_id = OBJECT_ID('migtest_e_basic','U') AND name = 'ix_migtest_e_basic_indextest5') drop index ix_migtest_e_basic_indextest5 ON migtest_e_basic; +alter table migtest_e_history + add sys_periodFrom datetime2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT SYSUTCDATETIME(), + sys_periodTo datetime2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT '9999-12-31T23:59:59.9999999', +period for system_time (sys_periodFrom, sys_periodTo); +alter table migtest_e_history set (system_versioning = on (history_table=dbo.migtest_e_history_history)); diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/1.2__dropsFor_1.1.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/1.2__dropsFor_1.1.sql new file mode 100644 index 000000000..08a80a5e5 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/1.2__dropsFor_1.1.sql @@ -0,0 +1,8 @@ +-- apply changes +alter table migtest_e_basic drop column old_boolean; + +alter table migtest_e_basic drop column old_boolean2; + +alter table migtest_e_basic drop column eref_id; + +IF OBJECT_ID('migtest_e_ref', 'U') IS NOT NULL drop table migtest_e_ref; diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/1.3.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/1.3.sql new file mode 100644 index 000000000..ea4a0b4f4 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/1.3.sql @@ -0,0 +1,27 @@ +-- apply changes +create table migtest_e_ref ( + id integer identity(1,1) not null, + constraint pk_migtest_e_ref primary key (id) +); + +alter table migtest_e_basic drop constraint ck_migtest_e_basic_status; +alter table migtest_e_basic drop constraint df_migtest_e_basic_status; +alter table migtest_e_basic add constraint ck_migtest_e_basic_status check ( status in ('N','A','I')); +alter table migtest_e_basic drop constraint uq_migtest_e_basic_description; +alter table migtest_e_basic drop constraint df_migtest_e_basic_some_date; + +update migtest_e_basic set user_id = 23 where user_id is null; +IF OBJECT_ID('fk_migtest_e_basic_user_id', 'F') IS NOT NULL alter table migtest_e_basic drop constraint fk_migtest_e_basic_user_id; +alter table migtest_e_basic add constraint df_migtest_e_basic_user_id default 23 for user_id; +alter table migtest_e_basic alter column user_id integer not null; +alter table migtest_e_basic add old_boolean bit default 0 not null; +alter table migtest_e_basic add old_boolean2 bit default 0; +alter table migtest_e_basic add eref_id integer; + +create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1); +create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5); +IF EXISTS (SELECT name FROM sys.indexes WHERE object_id = OBJECT_ID('migtest_e_basic','U') AND name = 'ix_migtest_e_basic_indextest3') drop index ix_migtest_e_basic_indextest3 ON migtest_e_basic; +IF EXISTS (SELECT name FROM sys.indexes WHERE object_id = OBJECT_ID('migtest_e_basic','U') AND name = 'ix_migtest_e_basic_indextest6') drop index ix_migtest_e_basic_indextest6 ON migtest_e_basic; +alter table migtest_e_basic add constraint fk_migtest_e_basic_eref_id foreign key (eref_id) references migtest_e_ref (id); +create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id); + diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/1.4__dropsFor_1.3.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/1.4__dropsFor_1.3.sql new file mode 100644 index 000000000..b3088fdd1 --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/1.4__dropsFor_1.3.sql @@ -0,0 +1,15 @@ +-- apply changes +alter table migtest_e_basic drop column new_string_field; + +alter table migtest_e_basic drop column new_boolean_field; + +alter table migtest_e_basic drop column new_boolean_field2; + +alter table migtest_e_basic drop column progress; + +alter table migtest_e_basic drop column new_integer; + +IF OBJECT_ID('migtest_e_user', 'U') IS NOT NULL drop table migtest_e_user; +alter table migtest_e_history set (system_versioning = off); +alter table migtest_e_history drop column sys_periodFrom; +alter table migtest_e_history drop column sys_periodTo; diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver/R__order_views_mssql.sql b/src/test/resources/dbmigration/migrationtest/sqlserver/R__order_views_mssql.sql new file mode 100644 index 000000000..3b90ebb2d --- /dev/null +++ b/src/test/resources/dbmigration/migrationtest/sqlserver/R__order_views_mssql.sql @@ -0,0 +1,10 @@ + + IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = 'order_agg_vw') + DROP VIEW order_agg_vw; + + create view order_agg_vw as + select d.order_id, sum(d.order_qty * d.unit_price) as order_total, + sum(d.ship_qty * d.unit_price) as ship_total + from o_order_detail d + group by d.order_id; + \ No newline at end of file diff --git a/src/test/resources/ebean.mf b/src/test/resources/ebean.mf index 49510b285..769eb471b 100644 --- a/src/test/resources/ebean.mf +++ b/src/test/resources/ebean.mf @@ -1,4 +1,4 @@ -entity-packages: org +entity-packages: org,misc transactional-packages: org querybean-packages: none diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties index 7375f601a..8f6a89abc 100644 --- a/src/test/resources/ebean.properties +++ b/src/test/resources/ebean.properties @@ -17,6 +17,7 @@ ebean.encryptKeyManager=org.tests.basic.encrypt.BasicEncyptKeyManager ebean.ddl.generate=true ebean.ddl.run=true +ebean.packages=org.tests datasource.default=h2 #ebean.persistBatch=NONE @@ -133,3 +134,15 @@ datasource.db2.username=db2admin datasource.db2.password=veryverysecret#1234 datasource.db2.databaseUrl=jdbc:db2://127.0.0.1:50000/SAMPLE datasource.db2.databaseDriver=com.ibm.db2.jcc.DB2Driver + +# parameters for migration test +datasource.migrationtest.username=SA +datasource.migrationtest.password=SA +datasource.migrationtest.databaseUrl=jdbc:h2:mem:migration +datasource.migrationtest.databaseDriver=org.h2.Driver +ebean.migrationtest.applyPrefix=V +ebean.migrationtest.ddl.generate=false +ebean.migrationtest.ddl.run=false +ebean.migrationtest.migration.appName=migrationtest +ebean.migrationtest.migration.migrationPath=dbmigration/migrationtest +ebean.migrationtest.migration.strict=true