001package io.ebeaninternal.dbmigration.ddlgeneration.platform; 002 003import io.ebean.config.DatabaseConfig; 004import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer; 005import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite; 006import io.ebeaninternal.dbmigration.migration.AddHistoryTable; 007import io.ebeaninternal.dbmigration.migration.DropHistoryTable; 008import io.ebeaninternal.dbmigration.model.MTable; 009 010import java.io.IOException; 011 012/** 013 * @author Vilmos Nagy 014 */ 015public class SqlServerHistoryDdl implements PlatformHistoryDdl { 016 017 private String systemPeriodStart; 018 private String systemPeriodEnd; 019 private PlatformDdl platformDdl; 020 021 @Override 022 public void configure(DatabaseConfig config, PlatformDdl platformDdl) { 023 this.systemPeriodStart = config.getAsOfSysPeriod() + "From"; 024 this.systemPeriodEnd = config.getAsOfSysPeriod() + "To"; 025 this.platformDdl = platformDdl; 026 } 027 028 @Override 029 public void createWithHistory(DdlWrite writer, MTable table) throws IOException { 030 String baseTable = table.getName(); 031 enableSystemVersioning(writer, baseTable); 032 } 033 034 String getHistoryTable(String baseTable) { 035 String historyTable = baseTable + "_history"; 036 if (baseTable.startsWith("[")) { 037 historyTable = historyTable.replace("]", "") + "]"; 038 } 039 if (historyTable.indexOf('.') == -1) { 040 // history must contain schema, add the default schema if none was specified 041 historyTable = "dbo." + historyTable; 042 } 043 return historyTable; 044 } 045 046 private void enableSystemVersioning(DdlWrite writer, String baseTable) throws IOException { 047 DdlBuffer apply = writer.applyHistoryView(); 048 apply.append("alter table ").append(baseTable).newLine() 049 .append(" add ").append(systemPeriodStart).append(" datetime2 GENERATED ALWAYS AS ROW START NOT NULL DEFAULT SYSUTCDATETIME(),").newLine() 050 .append(" ").append(systemPeriodEnd).append(" datetime2 GENERATED ALWAYS AS ROW END NOT NULL DEFAULT '9999-12-31T23:59:59.9999999',").newLine() 051 .append("period for system_time (").append(systemPeriodStart).append(", ").append(systemPeriodEnd).append(")").endOfStatement(); 052 053 apply.append("alter table ").append(baseTable).append(" set (system_versioning = on (history_table=") 054 .append(getHistoryTable(baseTable)).append("))").endOfStatement(); 055 056 DdlBuffer drop = writer.dropAll(); 057 drop.append("IF OBJECT_ID('").append(baseTable).append("', 'U') IS NOT NULL alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement(); 058 drop.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement(); 059 } 060 061 @Override 062 public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException { 063 String baseTable = dropHistoryTable.getBaseTable(); 064 DdlBuffer apply = writer.applyHistoryView(); 065 apply.append("-- dropping history support for ").append(baseTable).endOfStatement(); 066 // drop default constraints 067 068 apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodStart, DdlHelp.DROP_DEFAULT)).endOfStatement(); 069 apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodEnd, DdlHelp.DROP_DEFAULT)).endOfStatement(); 070 // switch of versioning & period 071 apply.append("alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement(); 072 apply.append("alter table ").append(baseTable).append(" drop period for system_time").endOfStatement(); 073 // now drop tables & columns 074 apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodStart).endOfStatement(); 075 apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodEnd).endOfStatement(); 076 apply.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement(); 077 apply.end(); 078 } 079 080 @Override 081 public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException { 082 String baseTable = addHistoryTable.getBaseTable(); 083 enableSystemVersioning(writer, baseTable); 084 } 085 086 @Override 087 public void updateTriggers(DdlWrite writer, HistoryTableUpdate baseTable) throws IOException { 088 // SQL Server 2016 does not need triggers 089 DdlBuffer apply = writer.applyHistoryView(); 090 String baseTableName = baseTable.getBaseTable(); 091 apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = off (history_table=") 092 .append(getHistoryTable(baseTableName)).append("))").endOfStatement(); 093 apply.append("-- history migration goes here").newLine(); 094 apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = on (history_table=") 095 .append(getHistoryTable(baseTableName)).append("))").endOfStatement(); 096 097 } 098}