001package io.ebeaninternal.dbmigration.ddlgeneration.platform;
002
003import io.ebean.config.DatabaseConfig;
004import io.ebeaninternal.dbmigration.ddlgeneration.DdlAlterTable;
005import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
006import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
007import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
008import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
009import io.ebeaninternal.dbmigration.model.MColumn;
010import io.ebeaninternal.dbmigration.model.MTable;
011
012import java.util.Collection;
013
014public class HanaHistoryDdl extends DbTableBasedHistoryDdl implements PlatformHistoryDdl {
015
016  private String systemPeriodStart;
017  private String systemPeriodEnd;
018
019  @Override
020  public void configure(DatabaseConfig config, PlatformDdl platformDdl) {
021    super.configure(config, platformDdl);
022    this.systemPeriodStart = config.getAsOfSysPeriod() + "_start";
023    this.systemPeriodEnd = config.getAsOfSysPeriod() + "_end";
024  }
025
026  @Override
027  public void createWithHistory(DdlWrite writer, MTable table) {
028    String tableName = table.getName();
029    String historyTableName = historyTableName(tableName);
030    DdlBuffer apply = writer.applyPostAlter();
031
032    apply.append(platformDdl.getCreateTableCommandPrefix()).append(" ").append(historyTableName).append(" (").newLine();
033
034    // create history table
035    Collection<MColumn> cols = table.allColumns();
036    for (MColumn column : cols) {
037      if (!column.isDraftOnly()) {
038        writeColumnDefinition(apply, column.getName(), column.getType(), column.getDefaultValue(), column.isNotnull(),
039          column.isIdentity() ? platformDdl.identitySuffix : null);
040        apply.append(",").newLine();
041      }
042    }
043    writeColumnDefinition(apply, systemPeriodStart, "TIMESTAMP", null, false, null);
044    apply.append(",").newLine();
045    writeColumnDefinition(apply, systemPeriodEnd, "TIMESTAMP", null, false, null);
046    apply.newLine().append(")").endOfStatement();
047
048    // enable system versioning
049    apply.append("alter table ").append(tableName).append(" add (").newLine();
050    apply.append("    ").append(systemPeriodStart).append(" TIMESTAMP NOT NULL GENERATED ALWAYS AS ROW START, ").newLine();
051    apply.append("    ").append(systemPeriodEnd).append(" TIMESTAMP NOT NULL GENERATED ALWAYS AS ROW END").newLine();
052    apply.append(")").endOfStatement();
053
054    apply.append("alter table ").append(tableName).append(" add period for system_time(").append(systemPeriodStart)
055      .append(",").append(systemPeriodEnd).append(")").endOfStatement();
056
057    enableSystemVersioning(apply, tableName, true);
058    platformDdl.alterTable(writer, tableName).setHistoryHandled();
059
060    dropHistoryTable(writer.dropAll(), tableName, historyTableName);
061  }
062
063  @Override
064  public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) {
065    dropHistoryTable(writer.applyDropDependencies(), dropHistoryTable.getBaseTable(),
066      historyTableName(dropHistoryTable.getBaseTable()));
067  }
068
069  protected void dropHistoryTable(DdlBuffer apply, String baseTable, String historyTable) {
070    // disable system versioning
071    disableSystemVersioning(apply, baseTable);
072
073    apply.append("alter table ").append(baseTable).append(" drop period for system_time").endOfStatement();
074
075    // drop the period columns
076    apply.append("alter table ").append(baseTable).append(" drop (").append(systemPeriodStart).append(",")
077      .append(systemPeriodEnd).append(")").endOfStatement();
078
079    // drop the history table
080    apply.append("drop table ").append(historyTable).append(" cascade").endOfStatement();
081  }
082
083  @Override
084  public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) {
085    MTable table = writer.getTable(addHistoryTable.getBaseTable());
086    if (table == null) {
087      throw new IllegalStateException("MTable " + addHistoryTable.getBaseTable() + " not found in writer? (required for history DDL)");
088    }
089    createWithHistory(writer, table);
090  }
091
092  @Override
093  public void updateTriggers(DdlWrite writer, String tableName) {
094    DdlAlterTable alter = platformDdl.alterTable(writer, tableName);
095    MTable table = writer.getTable(tableName);
096    if (table.isWithHistory() && !alter.isHistoryHandled()) {
097      disableSystemVersioning(writer.apply(), tableName);
098      enableSystemVersioning(writer.applyPostAlter(), tableName, false);
099      alter.setHistoryHandled();
100    }
101  }
102
103  protected void writeColumnDefinition(DdlBuffer buffer, String columnName, String type, String defaultValue,
104                                       boolean isNotNull, String generated) {
105
106    String platformType = platformDdl.convert(type);
107    buffer.append(" ").append(columnName);
108    buffer.append(" ").append(platformType);
109    if (defaultValue != null) {
110      buffer.append(" default ").append(defaultValue);
111    }
112    if (isNotNull) {
113      buffer.append(" not null");
114    }
115    if (generated != null) {
116      buffer.append(" ").append(generated);
117    }
118  }
119
120  public void disableSystemVersioning(DdlBuffer apply, String tableName) {
121    apply.append("alter table ").append(tableName).append(" drop system versioning").endOfStatement();
122  }
123
124  public void enableSystemVersioning(DdlBuffer apply, String tableName, boolean validated) {
125    apply.append("alter table ").append(tableName).append(" add system versioning history table ").append(historyTableName(tableName));
126    if (!validated) {
127      apply.append(" not validated");
128    }
129    apply.endOfStatement();
130  }
131
132
133}