diff --git a/src/main/java/com/avaje/ebean/config/ServerConfig.java b/src/main/java/com/avaje/ebean/config/ServerConfig.java index f52b7eea2..ce6792afc 100644 --- a/src/main/java/com/avaje/ebean/config/ServerConfig.java +++ b/src/main/java/com/avaje/ebean/config/ServerConfig.java @@ -162,6 +162,12 @@ public class ServerConfig { */ private String asOfSysPeriod = "sys_period"; + /** + * Suffix appended to the base table to derive the view that contains the union + * of the base table and the history table in order to support asOf queries. + */ + private String historyTableSuffix = "_history"; + /** * Use for transaction scoped batch mode. */ @@ -676,6 +682,20 @@ public class ServerConfig { this.asOfSysPeriod = asOfSysPeriod; } + /** + * Return the history table suffix (defaults to _history). + */ + public String getHistoryTableSuffix() { + return historyTableSuffix; + } + + /** + * Set the history table suffix. + */ + public void setHistoryTableSuffix(String historyTableSuffix) { + this.historyTableSuffix = historyTableSuffix; + } + /** * Return true if we are running in a JTA Transaction manager. */ @@ -1960,6 +1980,7 @@ public class ServerConfig { diffFlatMode = p.getBoolean("diffFlatMode", diffFlatMode); asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix); asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod); + historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix); dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName); databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize); databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue); diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java index 3cb08b322..57e05c723 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/BaseDdlHandler.java @@ -1,14 +1,15 @@ package com.avaje.ebean.dbmigration.ddlgeneration; -import com.avaje.ebean.config.DbConstraintNaming; -import com.avaje.ebean.config.NamingConvention; +import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.dbmigration.ddlgeneration.platform.BaseTableDdl; import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl; import com.avaje.ebean.dbmigration.migration.AddColumn; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; import com.avaje.ebean.dbmigration.migration.AlterColumn; import com.avaje.ebean.dbmigration.migration.ChangeSet; import com.avaje.ebean.dbmigration.migration.CreateTable; import com.avaje.ebean.dbmigration.migration.DropColumn; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import java.io.IOException; import java.util.List; @@ -20,8 +21,8 @@ public class BaseDdlHandler implements DdlHandler { protected final TableDdl tableDdl; - public BaseDdlHandler(NamingConvention namingConvention, DbConstraintNaming naming, PlatformDdl platformDdl) { - this.tableDdl = new BaseTableDdl(namingConvention, naming, platformDdl); + public BaseDdlHandler(ServerConfig serverConfig, PlatformDdl platformDdl) { + this.tableDdl = new BaseTableDdl(serverConfig, platformDdl); } @Override @@ -29,7 +30,7 @@ public class BaseDdlHandler implements DdlHandler { List changeSetChildren = changeSet.getChangeSetChildren(); for (Object change : changeSetChildren) { - if (change instanceof CreateTable) { + if (change instanceof CreateTable) { generate(writer, (CreateTable) change); } else if (change instanceof AddColumn) { generate(writer, (AddColumn) change); @@ -37,10 +38,19 @@ public class BaseDdlHandler implements DdlHandler { generate(writer, (DropColumn) change); } else if (change instanceof AlterColumn) { generate(writer, (AlterColumn) change); + } else if (change instanceof AddHistoryTable) { + generate(writer, (AddHistoryTable) change); + } else if (change instanceof DropHistoryTable) { + generate(writer, (DropHistoryTable) change); } } } + @Override + public void generateExtra(DdlWrite write) throws IOException { + tableDdl.generateExtra(write); + } + @Override public void generate(DdlWrite writer, CreateTable createTable) throws IOException { tableDdl.generate(writer, createTable); @@ -60,4 +70,14 @@ public class BaseDdlHandler implements DdlHandler { public void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException { tableDdl.generate(writer, alterColumn); } + + @Override + public void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { + tableDdl.generate(writer, addHistoryTable); + } + + @Override + public void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException { + tableDdl.generate(writer, dropHistoryTable); + } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/DdlHandler.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/DdlHandler.java index fa5f7b043..5506611d0 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/DdlHandler.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/DdlHandler.java @@ -1,10 +1,12 @@ package com.avaje.ebean.dbmigration.ddlgeneration; import com.avaje.ebean.dbmigration.migration.AddColumn; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; import com.avaje.ebean.dbmigration.migration.AlterColumn; import com.avaje.ebean.dbmigration.migration.ChangeSet; import com.avaje.ebean.dbmigration.migration.CreateTable; import com.avaje.ebean.dbmigration.migration.DropColumn; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import java.io.IOException; @@ -22,4 +24,9 @@ public interface DdlHandler { void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException; + void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException; + + void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException; + + void generateExtra(DdlWrite write) throws IOException; } \ No newline at end of file diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/TableDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/TableDdl.java index 7656955d0..45597f740 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/TableDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/TableDdl.java @@ -1,9 +1,11 @@ package com.avaje.ebean.dbmigration.ddlgeneration; import com.avaje.ebean.dbmigration.migration.AddColumn; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; import com.avaje.ebean.dbmigration.migration.AlterColumn; import com.avaje.ebean.dbmigration.migration.CreateTable; import com.avaje.ebean.dbmigration.migration.DropColumn; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.migration.DropTable; import java.io.IOException; @@ -37,4 +39,19 @@ public interface TableDdl { * Write the drop column change. */ void generate(DdlWrite writer, DropColumn dropColumn) throws IOException; + + /** + * Write the AddHistoryTable change. + */ + void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException; + + /** + * Write the DropHistoryTable change. + */ + void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException; + + /** + * Generate any extra DDL such as regeneration of history triggers. + */ + void generateExtra(DdlWrite write) throws IOException; } diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java index a0ed3caed..90ccac266 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -9,10 +9,12 @@ import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; import com.avaje.ebean.dbmigration.ddlgeneration.TableDdl; import com.avaje.ebean.dbmigration.ddlgeneration.platform.util.IndexSet; import com.avaje.ebean.dbmigration.migration.AddColumn; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; import com.avaje.ebean.dbmigration.migration.AlterColumn; import com.avaje.ebean.dbmigration.migration.Column; import com.avaje.ebean.dbmigration.migration.CreateTable; import com.avaje.ebean.dbmigration.migration.DropColumn; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.migration.DropTable; import com.avaje.ebean.dbmigration.migration.ForeignKey; import com.avaje.ebean.dbmigration.model.MTable; @@ -20,7 +22,9 @@ import com.avaje.ebean.dbmigration.model.MTable; import java.io.IOException; import java.math.BigInteger; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * Base implementation for 'create table' and 'alter table' statements. @@ -33,6 +37,8 @@ public class BaseTableDdl implements TableDdl { protected final PlatformDdl platformDdl; + private final String historyTableSuffix; + /** * Used to check that indexes on foreign keys should be skipped as a unique index on the columns * already exists. @@ -51,17 +57,20 @@ public class BaseTableDdl implements TableDdl { protected int countForeignKey; protected int countIndex; - public BaseTableDdl(ServerConfig serverConfig, PlatformDdl platformDdl) { - this(serverConfig.getNamingConvention(), serverConfig.getConstraintNaming(), platformDdl); - } + /** + * Base tables that have associated history tables that need their triggers + * regenerated as columns have been added or removed. + */ + protected Set regenerateHistoryTriggers = new LinkedHashSet(); /** * Construct with a naming convention and platform specific DDL. */ - public BaseTableDdl(NamingConvention namingConvention, DbConstraintNaming naming, PlatformDdl platformDdl) { - this.namingConvention = namingConvention; - this.naming = naming; + public BaseTableDdl(ServerConfig serverConfig, PlatformDdl platformDdl) { + this.namingConvention = serverConfig.getNamingConvention(); + this.naming = serverConfig.getConstraintNaming(); this.platformDdl = platformDdl; + this.historyTableSuffix = serverConfig.getHistoryTableSuffix(); } /** @@ -449,26 +458,52 @@ public class BaseTableDdl implements TableDdl { return pk; } + @Override + public void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { + platformDdl.addHistoryTable(writer, addHistoryTable); + } + + @Override + public void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException { + platformDdl.dropHistoryTable(writer, dropHistoryTable); + } + + @Override + public void generateExtra(DdlWrite write) throws IOException { + for (String baseTable : this.regenerateHistoryTriggers) { + platformDdl.regenerateHistoryTriggers(write, baseTable); + } + } + @Override public void generate(DdlWrite writer, AddColumn addColumn) throws IOException { String tableName = addColumn.getTableName(); List columns = addColumn.getColumn(); for (Column column : columns) { - // apply - alterTableAddColumn(writer.apply(), tableName, column); - - // rollback + alterTableAddColumn(writer.apply(), tableName, column, false); alterTableDropColumn(writer.rollback(), tableName, column.getName()); } + + if (isTrue(addColumn.isWithHistory())) { + // make same changes to the history table + String historyTable = historyTable(tableName); + regenerateHistoryTriggers(tableName); + for (Column column : columns) { + alterTableAddColumn(writer.apply(), historyTable, column, true); + alterTableDropColumn(writer.rollback(), historyTable, column.getName()); + } + } + + // add a bit of whitespace + writer.apply().end(); + writer.rollback().end(); } @Override public void generate(DdlWrite writer, DropTable dropTable) throws IOException { - String tableName = dropTable.getName(); - - dropTable(writer.drop(), tableName); + dropTable(writer.drop(), dropTable.getName()); } @Override @@ -477,16 +512,23 @@ public class BaseTableDdl implements TableDdl { String tableName = dropColumn.getTableName(); alterTableDropColumn(writer.drop(), tableName, dropColumn.getColumnName()); + if (isTrue(dropColumn.isWithHistory())) { + // also drop from the history table + regenerateHistoryTriggers(tableName); + alterTableDropColumn(writer.drop(), historyTable(tableName), dropColumn.getColumnName()); + } + + writer.drop().end(); } @Override public void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException { - if (isTrue(alterColumn.isHistoryExclude())) { - historyExcludeColumn(writer, alterColumn); - } else if (isFalse(alterColumn.isHistoryExclude())) { - historyIncludeColumn(writer, alterColumn); - } +// if (isTrue(alterColumn.isHistoryExclude())) { +// historyExcludeColumn(writer, alterColumn); +// } else if (isFalse(alterColumn.isHistoryExclude())) { +// historyIncludeColumn(writer, alterColumn); +// } if (hasValue(alterColumn.getDropForeignKey())) { alterColumnDropForeignKey(writer, alterColumn); @@ -524,6 +566,17 @@ public class BaseTableDdl implements TableDdl { } } + protected String historyTable(String baseTable) { + return baseTable + historyTableSuffix; + } + + /** + * Register the base table that we need to regenerate the history triggers on. + */ + protected void regenerateHistoryTriggers(String baseTableName) { + regenerateHistoryTriggers.add(baseTableName); + } + /** * This is mysql specific - alter all the base attributes of the column together. */ @@ -532,16 +585,21 @@ public class BaseTableDdl implements TableDdl { String ddl = platformDdl.alterColumnBaseAttributes(alter); if (hasValue(ddl)) { writer.apply().append(ddl).endOfStatement(); + if (isTrue(alter.isWithHistory()) && alter.getType() != null) { + // mysql and sqlserver column type change allowing nulls in the history table column + AlterColumn alterHistoryColumn = new AlterColumn(); + alterHistoryColumn.setTableName(historyTable(alter.getTableName())); + alterHistoryColumn.setColumnName(alter.getColumnName()); + alterHistoryColumn.setType(alter.getType()); + String histColumnDdl = platformDdl.alterColumnBaseAttributes(alterHistoryColumn); + writer.apply().append(histColumnDdl).endOfStatement(); + } } } protected void alterColumnDefaultValue(DdlWrite writer, AlterColumn alter) throws IOException { - String tableName = alter.getTableName(); - String columnName = alter.getColumnName(); - String defaultValue = alter.getDefaultValue(); - - String ddl = platformDdl.alterColumnDefaultValue(tableName, columnName, defaultValue); + String ddl = platformDdl.alterColumnDefaultValue(alter.getTableName(), alter.getColumnName(), alter.getDefaultValue()); if (hasValue(ddl)) { writer.apply().append(ddl).endOfStatement(); } @@ -549,11 +607,7 @@ public class BaseTableDdl implements TableDdl { protected void alterColumnNotnull(DdlWrite writer, AlterColumn alter) throws IOException { - String tableName = alter.getTableName(); - String columnName = alter.getColumnName(); - Boolean notnull = alter.isNotnull(); - - String ddl = platformDdl.alterColumnNotnull(tableName, columnName, notnull); + String ddl = platformDdl.alterColumnNotnull(alter.getTableName(), alter.getColumnName(), alter.isNotnull()); if (hasValue(ddl)) { writer.apply().append(ddl).endOfStatement(); } @@ -561,16 +615,18 @@ public class BaseTableDdl implements TableDdl { protected void alterColumnType(DdlWrite writer, AlterColumn alter) throws IOException { - String tableName = alter.getTableName(); - String columnName = alter.getColumnName(); - String type = alter.getType(); - - String ddl = platformDdl.alterColumnType(tableName, columnName, type); + String ddl = platformDdl.alterColumnType(alter.getTableName(), alter.getColumnName(), alter.getType()); if (hasValue(ddl)) { writer.apply().append(ddl).endOfStatement(); + if (isTrue(alter.isWithHistory())) { + // apply same type change to matching column in the history table + ddl = platformDdl.alterColumnType(historyTable(alter.getTableName()), alter.getColumnName(), alter.getType()); + writer.apply().append(ddl).endOfStatement(); + } } } + protected void alterColumnAddForeignKey(DdlWrite writer, AlterColumn alterColumn) throws IOException { String tableName = alterColumn.getTableName(); @@ -590,21 +646,16 @@ public class BaseTableDdl implements TableDdl { protected void alterColumnDropForeignKey(DdlWrite writer, AlterColumn alter) throws IOException { - String tableName = alter.getTableName(); - String fkName = alter.getDropForeignKey(); writer.apply() - .append(platformDdl.alterTableDropForeignKey(tableName, fkName)) + .append(platformDdl.alterTableDropForeignKey(alter.getTableName(), alter.getDropForeignKey())) .endOfStatement(); } protected void alterColumnDropUniqueConstraint(DdlWrite writer, AlterColumn alter) throws IOException { - String tableName = alter.getTableName(); - String uqName = alter.getDropUnique(); - writer.apply() - .append(platformDdl.dropIndex(uqName, tableName)) + .append(platformDdl.dropIndex(alter.getDropUnique(), alter.getTableName())) .endOfStatement(); } @@ -620,16 +671,14 @@ public class BaseTableDdl implements TableDdl { protected void addUniqueConstraint(DdlWrite writer, AlterColumn alter, String uqName) throws IOException { - String tableName = alter.getTableName(); - String columnName = alter.getColumnName(); + String[] cols = {alter.getColumnName()}; - String[] cols = {columnName}; writer.apply() - .append(platformDdl.createExternalUniqueForOneToOne(uqName, tableName, cols)) + .append(platformDdl.createExternalUniqueForOneToOne(uqName, alter.getTableName(), cols)) .endOfStatement(); writer.rollbackForeignKeys() - .append(platformDdl.dropIndex(uqName, tableName)) + .append(platformDdl.dropIndex(uqName, alter.getTableName())) .endOfStatement(); } @@ -638,30 +687,24 @@ public class BaseTableDdl implements TableDdl { buffer.append("alter table ").append(tableName) .append(" drop column ").append(columnName) - .endOfStatement().end(); + .endOfStatement(); } - protected void alterTableAddColumn(DdlBuffer buffer, String tableName, Column column) throws IOException { + protected void alterTableAddColumn(DdlBuffer buffer, String tableName, Column column, boolean onHistoryTable) throws IOException { buffer.append("alter table ").append(tableName) .append(" add column ").append(column.getName()) .append(" ").append(column.getType()); - if (isTrue(column.isNotnull())) { - buffer.append(" not null"); + if (!onHistoryTable) { + if (isTrue(column.isNotnull())) { + buffer.append(" not null"); + } + if (hasValue(column.getCheckConstraint())) { + buffer.append(" ").append(column.getCheckConstraint()); + } } - if (hasValue(column.getCheckConstraint())) { - buffer.append(" ").append(column.getCheckConstraint()); - } - buffer.endOfStatement().end(); - } - - protected void historyIncludeColumn(DdlWrite writer, AlterColumn alterColumn) { - platformDdl.historyIncludeColumn(writer, alterColumn); - } - - protected void historyExcludeColumn(DdlWrite writer, AlterColumn alterColumn) { - platformDdl.historyExcludeColumn(writer, alterColumn); + buffer.endOfStatement(); } protected boolean isFalse(Boolean value) { diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/NoHistorySupportDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/NoHistorySupportDdl.java index 6706aa793..014cf1885 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/NoHistorySupportDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/NoHistorySupportDdl.java @@ -2,6 +2,8 @@ package com.avaje.ebean.dbmigration.ddlgeneration.platform; import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.model.MTable; import java.io.IOException; @@ -21,4 +23,19 @@ public class NoHistorySupportDdl implements PlatformHistoryDdl { public void createWithHistory(DdlWrite writer, MTable table) throws IOException { // does nothing } + + @Override + public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) { + // does nothing + } + + @Override + public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { + // does nothing + } + + @Override + public void regenerateHistoryTriggers(DdlWrite write, String baseTable) { + // does nothing + } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java index ac9caaf54..9091bd54d 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -8,7 +8,9 @@ import com.avaje.ebean.dbmigration.ddlgeneration.BaseDdlHandler; import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler; import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; import com.avaje.ebean.dbmigration.ddlgeneration.platform.util.PlatformTypeConverter; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; import com.avaje.ebean.dbmigration.migration.AlterColumn; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.migration.IdentityType; import com.avaje.ebean.dbmigration.model.MTable; @@ -76,7 +78,7 @@ public class PlatformDdl { public DdlHandler createDdlHandler(ServerConfig serverConfig) { historyDdl.configure(serverConfig); - return new BaseDdlHandler(serverConfig.getNamingConvention(), serverConfig.getConstraintNaming(), this); + return new BaseDdlHandler(serverConfig, this); } public IdType useIdentityType(IdentityType modelIdentityType) { @@ -120,6 +122,18 @@ public class PlatformDdl { historyDdl.createWithHistory(writer, table); } + public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException { + historyDdl.dropHistoryTable(writer, dropHistoryTable); + } + + public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { + historyDdl.addHistoryTable(writer, addHistoryTable); + } + + public void regenerateHistoryTriggers(DdlWrite write, String baseTable) throws IOException { + historyDdl.regenerateHistoryTriggers(write, baseTable); + } + /** * Generate and return the create sequence DDL. */ @@ -176,15 +190,6 @@ public class PlatformDdl { return ""; } - public void historyExcludeColumn(DdlWrite writer, AlterColumn alterColumn) { - - } - - public void historyIncludeColumn(DdlWrite writer, AlterColumn alterColumn) { - - } - - public String alterColumnType(String tableName, String columnName, String type) { return "alter table " + tableName + " " + alterColumn + " " + columnName + " " + columnSetType + type; diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformHistoryDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformHistoryDdl.java index 48da0862b..d1169a6f4 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformHistoryDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PlatformHistoryDdl.java @@ -2,6 +2,8 @@ package com.avaje.ebean.dbmigration.ddlgeneration.platform; import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.model.MTable; import java.io.IOException; @@ -13,7 +15,6 @@ public interface PlatformHistoryDdl { /** * Configure typically reading the - * @param serverConfig */ void configure(ServerConfig serverConfig); @@ -22,4 +23,9 @@ public interface PlatformHistoryDdl { */ void createWithHistory(DdlWrite writer, MTable table) throws IOException; + void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException; + + void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException; + + void regenerateHistoryTriggers(DdlWrite write, String baseTable) throws IOException; } diff --git a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PostgresHistoryDdl.java b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PostgresHistoryDdl.java index ca54f2783..0fdeba4b2 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PostgresHistoryDdl.java +++ b/src/main/java/com/avaje/ebean/dbmigration/ddlgeneration/platform/PostgresHistoryDdl.java @@ -4,6 +4,8 @@ import com.avaje.ebean.config.DbConstraintNaming; import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.dbmigration.ddlgeneration.DdlBuffer; import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite; +import com.avaje.ebean.dbmigration.migration.AddHistoryTable; +import com.avaje.ebean.dbmigration.migration.DropHistoryTable; import com.avaje.ebean.dbmigration.model.MColumn; import com.avaje.ebean.dbmigration.model.MTable; @@ -21,7 +23,7 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { private String viewSuffix; - private String historySuffix = "_history"; + private String historySuffix; public PostgresHistoryDdl() { } @@ -30,20 +32,51 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { public void configure(ServerConfig serverConfig) { this.sysPeriod = serverConfig.getAsOfSysPeriod(); this.viewSuffix = serverConfig.getAsOfViewSuffix(); + this.historySuffix = serverConfig.getHistoryTableSuffix(); this.constraintNaming = serverConfig.getConstraintNaming(); } + @Override + public void regenerateHistoryTriggers(DdlWrite writer, String baseTable) throws IOException { + + MTable table = writer.getTable(baseTable); + if (table == null) { + throw new IllegalStateException("MTable "+baseTable+" not found in writer? (required for history DDL)"); + } + addStoredFunction(writer, table); + } + + @Override + public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException { + + String baseTable = dropHistoryTable.getBaseTable(); + + // drop in appropriate order + dropTriggersEtc(writer.dropHistory(), baseTable); + dropHistoryTableEtc(writer.dropHistory(), baseTable); + } + + + @Override + public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { + + String baseTable = addHistoryTable.getBaseTable(); + MTable table = writer.getTable(baseTable); + if (table == null) { + throw new IllegalStateException("MTable "+baseTable+" not found in writer? (required for history DDL)"); + } + + createWithHistory(writer, table); + } + @Override public void createWithHistory(DdlWrite writer, MTable table) throws IOException { - String baseTable = table.getName(); - // rollback trigger then function - DdlBuffer rollback = writer.rollback(); - rollback.append("drop trigger if exists ").append(triggerName(baseTable)).append(" on ").append(baseTable).append(" cascade").endOfStatement(); - rollback.append("drop function if exists ").append(procedureName(baseTable)).append("()").endOfStatement(); - rollback.end(); + // rollback changes in appropriate order + dropTriggersEtc(writer.rollback(), baseTable); + dropHistoryTableEtc(writer.rollback(), baseTable); addHistoryTable(writer, table); addStoredFunction(writer, table); @@ -66,7 +99,15 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { return normalise(baseTableName) + "_history_upd"; } - public void addHistoryTable(DdlWrite writer, MTable table) throws IOException { + protected void dropTriggersEtc(DdlBuffer buffer, String baseTable) throws IOException { + + // rollback trigger then function + buffer.append("drop trigger if exists ").append(triggerName(baseTable)).append(" on ").append(baseTable).append(" cascade").endOfStatement(); + buffer.append("drop function if exists ").append(procedureName(baseTable)).append("()").endOfStatement(); + buffer.end(); + } + + protected void addHistoryTable(DdlWrite writer, MTable table) throws IOException { String baseTableName = table.getName(); @@ -87,15 +128,16 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { .append(" as select * from ").append(baseTableName) .append(" union all select * from ").append(baseTableName).append(historySuffix) .endOfStatement().end(); - - // rollback changes in appropriate order - DdlBuffer rollback = writer.rollback(); - rollback.append("drop view ").append(baseTableName).append(viewSuffix).endOfStatement(); - rollback.append("alter table ").append(baseTableName).append(" drop column ").append(sysPeriod).endOfStatement(); - rollback.append("drop table ").append(baseTableName).append(historySuffix).endOfStatement().end(); } - public void addTrigger(DdlWrite writer, MTable table) throws IOException { + protected void dropHistoryTableEtc(DdlBuffer buffer, String baseTableName) throws IOException { + + buffer.append("drop view ").append(baseTableName).append(viewSuffix).endOfStatement(); + buffer.append("alter table ").append(baseTableName).append(" drop column ").append(sysPeriod).endOfStatement(); + buffer.append("drop table ").append(baseTableName).append(historySuffix).endOfStatement().end(); + } + + protected void addTrigger(DdlWrite writer, MTable table) throws IOException { String baseTableName = table.getName(); String procedureName = procedureName(baseTableName); @@ -108,7 +150,7 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { .append(" for each row execute procedure ").append(procedureName).append("();").newLine().newLine(); } - public void addStoredFunction(DdlWrite writer, MTable table) throws IOException { + protected void addStoredFunction(DdlWrite writer, MTable table) throws IOException { String procedureName = procedureName(table.getName()); @@ -142,7 +184,7 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { protected void appendInsertIntoHistory(DdlBuffer buffer, MTable table) throws IOException { - String historyTable = historyTableName(table.getName()); + String historyTable = historyTableName(table.getName()); buffer.append(" insert into ").append(historyTable).append(" (").append(sysPeriod).append(","); appendColumnNames(buffer, table, ""); @@ -156,11 +198,13 @@ public class PostgresHistoryDdl implements PlatformHistoryDdl { Collection columns = table.getColumns().values(); int i = 0; for (MColumn column : columns) { - if (++i > 1) { - buffer.append(", "); + if (!column.isHistoryExclude()) { + if (++i > 1) { + buffer.append(", "); + } + buffer.append(columnPrefix); + buffer.append(column.getName()); } - buffer.append(columnPrefix); - buffer.append(column.getName()); } } } diff --git a/src/main/java/com/avaje/ebean/dbmigration/migration/DropColumn.java b/src/main/java/com/avaje/ebean/dbmigration/migration/DropColumn.java index 06c3fe6db..03d42b2bf 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/migration/DropColumn.java +++ b/src/main/java/com/avaje/ebean/dbmigration/migration/DropColumn.java @@ -19,6 +19,7 @@ import javax.xml.bind.annotation.XmlType; * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <attribute name="columnName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> * <attribute name="tableName" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="withHistory" type="{http://www.w3.org/2001/XMLSchema}boolean" /> * </restriction> * </complexContent> * </complexType> @@ -35,6 +36,8 @@ public class DropColumn { protected String columnName; @XmlAttribute(name = "tableName", required = true) protected String tableName; + @XmlAttribute(name = "withHistory") + protected Boolean withHistory; /** * Gets the value of the columnName property. @@ -84,4 +87,28 @@ public class DropColumn { this.tableName = value; } + /** + * Gets the value of the withHistory property. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isWithHistory() { + return withHistory; + } + + /** + * Sets the value of the withHistory property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setWithHistory(Boolean value) { + this.withHistory = value; + } + } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java index 3d49c753d..e70e6f505 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/MTable.java @@ -163,11 +163,6 @@ public class MTable { } if (addColumn != null) { - if (withHistory) { - // These addColumns need to occur on the history - // table as well as the base table - addColumn.setWithHistory(Boolean.TRUE); - } modelDiff.addAddColumn(addColumn); } } @@ -379,6 +374,11 @@ public class MTable { if (addColumn == null) { addColumn = new AddColumn(); addColumn.setTableName(name); + if (withHistory) { + // These addColumns need to occur on the history + // table as well as the base table + addColumn.setWithHistory(Boolean.TRUE); + } } addColumn.getColumn().add(newColumn.createColumn()); @@ -389,6 +389,11 @@ public class MTable { DropColumn dropColumn = new DropColumn(); dropColumn.setTableName(name); dropColumn.setColumnName(existingColumn.getName()); + if (withHistory) { + // These dropColumns should occur on the history + // table as well as the base table + dropColumn.setWithHistory(Boolean.TRUE); + } modelDiff.addDropColumn(dropColumn); } diff --git a/src/main/java/com/avaje/ebean/dbmigration/model/ModelDdlWriter.java b/src/main/java/com/avaje/ebean/dbmigration/model/ModelDdlWriter.java index d8da80a8e..ebd97f71e 100644 --- a/src/main/java/com/avaje/ebean/dbmigration/model/ModelDdlWriter.java +++ b/src/main/java/com/avaje/ebean/dbmigration/model/ModelDdlWriter.java @@ -49,6 +49,7 @@ public class ModelDdlWriter { handler.generate(write, changeSet); } } + handler.generateExtra(write); return changeSetCount > 0; } diff --git a/src/main/resources/ebean-dbmigration-1.0.xsd b/src/main/resources/ebean-dbmigration-1.0.xsd index a785f3239..b11d1d14d 100644 --- a/src/main/resources/ebean-dbmigration-1.0.xsd +++ b/src/main/resources/ebean-dbmigration-1.0.xsd @@ -207,6 +207,7 @@ +