mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
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
This commit is contained in:
committed by
Rob Bygrave
parent
73b3d1d977
commit
dd8fff0277
@@ -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 <b>EXPERMIENTAL</b> 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();
|
||||
}
|
||||
@@ -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 <b>EXPERMIENTAL</b> 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:
|
||||
* <pre>
|
||||
* UPDATE table SET column = 'foo' WHERE column IS NULL
|
||||
* </pre>
|
||||
*/
|
||||
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 {};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String, String> 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.
|
||||
* <p>
|
||||
* Note: There are some special cases:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Normal Quoting: <code>@DbDefault("User's default")</code> on a String propery
|
||||
* returns: <code>default 'User''s default'</code><br/>
|
||||
* (the same on an integer property will throw a NumberFormatException)</li>
|
||||
* <li>Special case null: <code>@DbDefault("null")</code> will return this: <code>default null</code><br/>
|
||||
* If you need really the String "null", you have to specify <code>@DbDefault("'null'")</code>
|
||||
* which gives you the <code>default 'null'</code> statement.</li>
|
||||
* <li>Any statement, that begins and ends with single quote will not be checked or get quoted again.</li>
|
||||
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
|
||||
* a <code>default N'SANDNES'</code> in DDL. Note that this is platform specific!</li>
|
||||
* </ul>
|
||||
*/
|
||||
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 <code>value</code> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String, HistoryTableUpdate> 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<String> before;
|
||||
private List<String> 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<String> getScriptsForPlatform(List<DdlScript> scripts, String searchPlatform) {
|
||||
List<String> 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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <unknown> -- 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();
|
||||
|
||||
@@ -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;
|
||||
* </pre>
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "")
|
||||
@XmlType(name = "", propOrder = {
|
||||
"before", "after"
|
||||
})
|
||||
@XmlRootElement(name = "alterColumn")
|
||||
public class AlterColumn {
|
||||
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> before;
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> 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<DdlScript> getBefore() {
|
||||
if (before == null) {
|
||||
before = new ArrayList<>();
|
||||
}
|
||||
return before;
|
||||
}
|
||||
|
||||
public List<DdlScript> getAfter() {
|
||||
if (after == null) {
|
||||
after = new ArrayList<>();
|
||||
}
|
||||
return after;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<DdlScript> before;
|
||||
@XmlElement(required = false)
|
||||
protected List<DdlScript> 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<DdlScript> 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<DdlScript> getAfter() {
|
||||
if (after == null) {
|
||||
after = new ArrayList<>();
|
||||
}
|
||||
return after;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
* <p>
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
* <p>
|
||||
* <pre>
|
||||
* TODO @Rob: Can this generated automatically?
|
||||
* </pre>
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"ddl"
|
||||
})
|
||||
@XmlRootElement(name = "ddl-script")
|
||||
public class DdlScript {
|
||||
|
||||
@XmlValue
|
||||
protected List<String> ddl;
|
||||
|
||||
@XmlAttribute(name = "platforms")
|
||||
protected String platforms;
|
||||
|
||||
/**
|
||||
* Gets the value of the value property.
|
||||
*
|
||||
* @return possible object is
|
||||
* {@link String }
|
||||
*/
|
||||
public List<String> getDdl() {
|
||||
if (ddl == null) {
|
||||
ddl = new ArrayList<>();
|
||||
}
|
||||
return ddl;
|
||||
}
|
||||
|
||||
public void setDdl(List<String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<DbMigrationInfo> 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<DbMigrationInfo> dbMigrationInfos) {
|
||||
this.dbMigrationInfos = dbMigrationInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply changes based on the AlterColumn request.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<DbMigrationInfo> 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<DbMigrationInfo> getDbMigrationInfos() {
|
||||
return dbMigrationInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean Field associated with this property.
|
||||
*/
|
||||
|
||||
@@ -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<String> preAdd;
|
||||
private final List<String> postAdd;
|
||||
private final List<String> preAlter;
|
||||
private final List<String> postAlter;
|
||||
private final List<Platform> 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 <T> List<T> toList(T[] scripts) {
|
||||
if (scripts.length == 0) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.unmodifiableList(Arrays.asList(scripts));
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getPreAdd() {
|
||||
return preAdd;
|
||||
}
|
||||
public List<String> getPostAdd() {
|
||||
return postAdd;
|
||||
}
|
||||
public List<String> getPreAlter() {
|
||||
return preAlter;
|
||||
}
|
||||
public List<String> getPostAlter() {
|
||||
return postAlter;
|
||||
}
|
||||
public List<Platform> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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<DbMigrationInfo> 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<DbMigrationInfo> getDbMigrationInfos() {
|
||||
return dbMigrationInfos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> 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) {
|
||||
|
||||
Reference in New Issue
Block a user