From 4fe6f0cb133ac2a20b7ddde9256f53649ac9f7f7 Mon Sep 17 00:00:00 2001 From: NSzemenyei <63635801+NSzemenyei@users.noreply.github.com> Date: Fri, 4 Feb 2022 13:04:34 +0100 Subject: [PATCH] NEU: Db2 Tablespaces (#59) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * first commit * second commit, it works for db2 * create table index in TS * IndexTS & runPlacholdersMap * Zwischencommit * Implemented Tablespaces * Update PR * Zwischencommit * release.md * add lobTablespace support * ebean-annotation 7.7 * create index in TS ausgebaut * Fix Mergekonflikte * Migrationsskripte neu generiert * Revert "Migrationsskripte neu generiert" This reverts commit 2690718b92701c0f34661d309c129b97e3cbe053. * Revert "Fix Mergekonflikte" This reverts commit e073e25048af88205259fd6b0873c4227b27d205. * revert merge commit * Resolved merge commits * FIX: More merge conflicts and compile errors * FIX: platform.base problem * tableName uppercase * Reviewkommentare Teil 1 * Reviewkommentare Teil 2 * DbMigrationTest für DB2 gefixt * revert whitespaces * Review * review Co-authored-by: Roland Praml --- ebean-api/pom.xml | 2 +- .../server/deploy/BeanDescriptor.java | 9 + .../server/deploy/TablespaceMeta.java | 63 +++ .../deploy/meta/DeployBeanDescriptor.java | 10 + .../server/deploy/parse/AnnotationClass.java | 14 + .../ddlgeneration/BaseDdlHandler.java | 8 + .../dbmigration/ddlgeneration/DdlHandler.java | 3 + .../dbmigration/ddlgeneration/TableDdl.java | 6 + .../ddlgeneration/platform/BaseTableDdl.java | 31 +- .../ddlgeneration/platform/DB2Ddl.java | 25 +- .../ddlgeneration/platform/DdlHelp.java | 13 + .../ddlgeneration/platform/PlatformDdl.java | 19 +- .../dbmigration/migration/AlterTable.java | 526 ++++++++++++++++++ .../dbmigration/migration/ChangeSet.java | 1 + .../dbmigration/migration/CreateTable.java | 22 + .../dbmigration/migration/ObjectFactory.java | 8 + .../dbmigration/model/MTable.java | 82 ++- .../dbmigration/model/ModelContainer.java | 30 + .../dbmigration/model/ModelDiff.java | 8 + .../model/build/ModelBuildElementTable.java | 2 +- .../build/ModelBuildIntersectionTable.java | 2 +- .../main/resources/ebean-dbmigration-1.0.xsd | 23 + .../platform/PlatformDdl_CreateIndexTest.java | 8 + .../model/ModelContainerApplyTest.java | 4 +- .../resources/application-test.properties | 2 - .../dbmigration/DbMigrationTest.java | 4 + .../test/java/misc/migration/v1_0/EBasic.java | 2 + .../java/misc/migration/v1_1/MtmChild.java | 4 + .../java/misc/migration/v1_1/MtmMaster.java | 4 + ...ascadeDeleteChildrenWithCompositeKeys.java | 1 - ebean-test/src/test/resources/extra-ddl.xml | 31 ++ .../dbmigration/db2luw/1.0__initial.sql | 2 +- .../migrationtest/dbmigration/db2luw/1.1.sql | 9 +- .../migrationtest/dbmigration/db2luw/1.3.sql | 2 + .../db2luw/I__create_tablespaces.sql | 29 + .../dbmigration/db2luw/idx_db2.migrations | 7 +- .../dbmigration/model/1.0__initial.model.xml | 2 +- .../dbmigration/model/1.1.model.xml | 9 +- .../dbmigration/model/1.3.model.xml | 2 + ebean-test/testconfig/ebean-db2.properties | 4 +- release.md | 5 + 41 files changed, 996 insertions(+), 42 deletions(-) create mode 100644 ebean-core/src/main/java/io/ebeaninternal/server/deploy/TablespaceMeta.java create mode 100644 ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/AlterTable.java create mode 100644 ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/I__create_tablespaces.sql diff --git a/ebean-api/pom.xml b/ebean-api/pom.xml index 0f16f6e19..cd87aeb5e 100644 --- a/ebean-api/pom.xml +++ b/ebean-api/pom.xml @@ -49,7 +49,7 @@ io.ebean ebean-annotation - 7.6 + 7.7 diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index 305525bb3..1826caebe 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -121,6 +121,7 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { private final boolean softDelete; private final String draftTable; private final PartitionMeta partitionMeta; + private final TablespaceMeta tablespaceMeta; private final String storageEngine; private final String dbComment; private final boolean readAuditing; @@ -275,6 +276,7 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { this.dependentTables = deploy.getDependentTables(); this.dbComment = deploy.getDbComment(); this.partitionMeta = deploy.getPartitionMeta(); + this.tablespaceMeta = deploy.getTablespaceMeta(); this.storageEngine = deploy.getStorageEngine(); this.autoTunable = beanFinder == null && (entityType == EntityType.ORM || entityType == EntityType.VIEW); // helper object used to derive lists of properties @@ -2671,6 +2673,13 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { public PartitionMeta partitionMeta() { return partitionMeta; } + + /** + * Return the tablespace details of the bean. + */ + public TablespaceMeta tablespaceMeta() { + return tablespaceMeta; + } /** * Return the storage engine. diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/TablespaceMeta.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/TablespaceMeta.java new file mode 100644 index 000000000..40aedfe6b --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/TablespaceMeta.java @@ -0,0 +1,63 @@ +package io.ebeaninternal.server.deploy; + +import java.util.Objects; + +/** + * Meta data for table spaces. + * If table space is configured, tablespaceName, indexTablespace, lobTablespace is never null; + * + * @author Noemi Szemenyei, FOCONIS AG + * + */ +public final class TablespaceMeta { + + private final String tablespaceName; + private final String indexTablespace; + private final String lobTablespace; + + + public TablespaceMeta(String tablespaceName, String indexTablespace, String lobTablespace) { + this.tablespaceName = tablespaceName; + this.indexTablespace = indexTablespace; + this.lobTablespace = lobTablespace; + } + + public String getTablespaceName() { + return tablespaceName; + } + + public String getIndexTablespace() { + return indexTablespace; + } + + public String getLobTablespace() { + return lobTablespace; + } + + @Override + public int hashCode() { + return Objects.hash(indexTablespace, tablespaceName, lobTablespace); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + TablespaceMeta other = (TablespaceMeta) obj; + return Objects.equals(indexTablespace, other.indexTablespace) + && Objects.equals(tablespaceName, other.tablespaceName) + && Objects.equals(lobTablespace, other.lobTablespace); + } + + + + @Override + public String toString() { + return "tablespace=" + tablespaceName + ", indexTablespace=" + indexTablespace + ", lobTablespace=" + lobTablespace; + } + +} diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java index 7d1f2a1ae..38bd5aaac 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java @@ -35,6 +35,7 @@ import io.ebeaninternal.server.deploy.IndexDefinition; import io.ebeaninternal.server.deploy.InheritInfo; import io.ebeaninternal.server.deploy.PartitionMeta; import io.ebeaninternal.server.deploy.TableJoin; +import io.ebeaninternal.server.deploy.TablespaceMeta; import io.ebeaninternal.server.deploy.parse.DeployBeanInfo; import io.ebeaninternal.server.idgen.UuidV1IdGenerator; import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator; @@ -140,6 +141,7 @@ public class DeployBeanDescriptor implements DeployBeanDescriptorMeta { private ChangeLogFilter changeLogFilter; private String dbComment; private PartitionMeta partitionMeta; + private TablespaceMeta tablespaceMeta; /** * One of NONE, INDEX or EMBEDDED. */ @@ -261,6 +263,14 @@ public class DeployBeanDescriptor implements DeployBeanDescriptorMeta { } return partitionMeta; } + + public void setTablespaceMeta(TablespaceMeta tablespaceMeta) { + this.tablespaceMeta = tablespaceMeta; + } + + public TablespaceMeta getTablespaceMeta() { + return tablespaceMeta; + } public void setDraftable() { draftable = true; diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationClass.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationClass.java index d9061e9e9..1ce197f61 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationClass.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/parse/AnnotationClass.java @@ -14,6 +14,7 @@ import io.ebean.annotation.Index; import io.ebean.annotation.InvalidateQueryCache; import io.ebean.annotation.ReadAudit; import io.ebean.annotation.StorageEngine; +import io.ebean.annotation.Tablespace; import io.ebean.annotation.View; import io.ebean.config.TableName; import io.ebean.util.AnnotationUtil; @@ -22,6 +23,7 @@ import io.ebeaninternal.server.deploy.BeanDescriptor.EntityType; import io.ebeaninternal.server.deploy.IndexDefinition; import io.ebeaninternal.server.deploy.InheritInfo; import io.ebeaninternal.server.deploy.PartitionMeta; +import io.ebeaninternal.server.deploy.TablespaceMeta; import io.ebeaninternal.server.deploy.meta.DeployBeanProperty; import javax.persistence.AttributeOverride; @@ -158,6 +160,18 @@ final class AnnotationClass extends AnnotationParser { if (partition != null) { descriptor.setPartitionMeta(new PartitionMeta(partition.mode(), partition.property())); } + Tablespace tablespace = typeGet(cls, Tablespace.class); + if (tablespace != null) { + String indexTs = tablespace.index(); + if("".equals(indexTs)) { + indexTs = tablespace.value(); + } + String lobTs = tablespace.lob(); + if("".equals(lobTs)) { + lobTs = tablespace.value(); + } + descriptor.setTablespaceMeta(new TablespaceMeta(tablespace.value(), indexTs, lobTs)); + } Draftable draftable = typeGet(cls, Draftable.class); if (draftable != null) { descriptor.setDraftable(); diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java index 870d90472..f84c19cda 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/BaseDdlHandler.java @@ -9,6 +9,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.ChangeSet; import io.ebeaninternal.dbmigration.migration.CreateIndex; import io.ebeaninternal.dbmigration.migration.CreateTable; @@ -49,6 +50,8 @@ public class BaseDdlHandler implements DdlHandler { // ignore } else if (change instanceof DropTable) { generate(writer, (DropTable) change); + } else if (change instanceof AlterTable) { + generate(writer, (AlterTable) change); } else if (change instanceof AddTableComment) { generate(writer, (AddTableComment) change); } else if (change instanceof CreateIndex) { @@ -94,6 +97,11 @@ public class BaseDdlHandler implements DdlHandler { public void generate(DdlWrite writer, DropTable dropTable) throws IOException { tableDdl.generate(writer, dropTable); } + + @Override + public void generate(DdlWrite writer, AlterTable alterTable) throws IOException { + tableDdl.generate(writer, alterTable); + } @Override public void generate(DdlWrite writer, AddTableComment addTableComment) throws IOException { diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java index 9a693640f..738e9a1dc 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/DdlHandler.java @@ -6,6 +6,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.ChangeSet; import io.ebeaninternal.dbmigration.migration.CreateIndex; import io.ebeaninternal.dbmigration.migration.CreateTable; @@ -26,6 +27,8 @@ public interface DdlHandler { void generate(DdlWrite writer, CreateTable createTable) throws IOException; void generate(DdlWrite writer, DropTable dropTable) throws IOException; + + void generate(DdlWrite writer, AlterTable dropTable) throws IOException; void generate(DdlWrite writer, AddTableComment addTableComment) throws IOException; diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java index 1ef34384b..f88546b62 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/TableDdl.java @@ -6,6 +6,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.CreateIndex; import io.ebeaninternal.dbmigration.migration.CreateTable; import io.ebeaninternal.dbmigration.migration.DropColumn; @@ -29,6 +30,11 @@ public interface TableDdl { * Write the drop column change. */ void generate(DdlWrite writer, DropTable dropTable) throws IOException; + + /** + * Write alter table changes. + */ + void generate(DdlWrite writer, AlterTable dropTable) throws IOException; /** * Write the add column change. diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java index 1acbd7acd..c4715fde3 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -18,6 +18,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.Column; import io.ebeaninternal.dbmigration.migration.CreateIndex; import io.ebeaninternal.dbmigration.migration.CreateTable; @@ -198,7 +199,7 @@ public class BaseTableDdl implements TableDdl { private void handleStrictError(String tableName, String columnName) { if (strictMode) { - String message = "DB Migration of non-null column with no default value specified for: " + tableName + "." + columnName+" Use @DbDefault to specify a default value or specify dbMigration.setStrictMode(false)"; + String message = "DB Migration of non-null column with no default value specified for: " + tableName + "." + columnName+" Use @DbDefault to specify a default value or disable strict mode for migration"; throw new IllegalArgumentException(message); } } @@ -279,6 +280,10 @@ public class BaseTableDdl implements TableDdl { writeInlineForeignKeys(writer, createTable); } apply.newLine().append(")"); + if (createTable.getTablespace() != null) { + platformDdl.addTablespace(apply, createTable.getTablespace(), createTable.getIndexTablespace(), + createTable.getLobTablespace()); + } addTableStorageEngine(apply, createTable); addTableCommentInline(apply, createTable); if (partitionMode != null) { @@ -582,12 +587,12 @@ public class BaseTableDdl implements TableDdl { } return pk; } - + @Override public void generate(DdlWrite writer, CreateIndex index) throws IOException { if (platformInclude(index.getPlatforms())) { flushReorgTables(writer.apply()); - writer.apply().appendStatement(platformDdl.createIndex(new WriteCreateIndex(index))); + writer.apply().appendStatement(platformDdl.createIndex(new WriteCreateIndex(index))); writer.dropAll().appendStatement(platformDdl.dropIndex(index.getIndexName(), index.getTableName(), Boolean.TRUE.equals(index.isConcurrent()))); } } @@ -712,6 +717,26 @@ public class BaseTableDdl implements TableDdl { } } + @Override + public void generate(DdlWrite writer, AlterTable alterTable) throws IOException { + if (hasValue(alterTable.getTablespace()) || hasValue(alterTable.getIndexTablespace()) || hasValue(alterTable.getLobTablespace())) { + writer.apply().appendStatement(platformDdl.alterTableTablespace(alterTable.getName(), + DdlHelp.toTablespace(alterTable.getTablespace()), + DdlHelp.toTablespace(alterTable.getIndexTablespace()), + DdlHelp.toTablespace(alterTable.getLobTablespace()))); + } + } + + protected void writeTablespaceChange(DdlBuffer buffer, String tablename, String tableSpace, String indexSpace, + String lobSpace) throws IOException { + buffer.appendStatement("-- TableSpace changed: Table: " + tablename + ", tableSpace " + tableSpace + ", indexSpace " + + indexSpace + ", lobSpace " + lobSpace); + if (strictMode) { + throw new UnsupportedOperationException( + "Tablespace change is not supported by this platform. Disable strict mode for migration and write migration manually"); + } + } + /** * Add drop column DDL. */ diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java index 44585c73b..aa1a95494 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DB2Ddl.java @@ -1,7 +1,10 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform; +import java.io.IOException; + import io.ebean.annotation.ConstraintMode; import io.ebean.config.dbplatform.DatabasePlatform; +import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer; /** * DB2 platform specific DDL. @@ -29,7 +32,8 @@ import io.ebean.config.dbplatform.DatabasePlatform; * */ public class DB2Ddl extends PlatformDdl { - + private static final String MOVE_TABLE = "CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'%s','%s','%s','%s','','','','','','MOVE')"; + public DB2Ddl(DatabasePlatform platform) { super(platform); this.dropTableIfExists = "drop table "; @@ -42,6 +46,16 @@ public class DB2Ddl extends PlatformDdl { this.inlineUniqueWhenNullable = false; } + @Override + public String alterTableTablespace(String tablename, String tableSpace, String indexSpace, String lobSpace) { + if(tableSpace == null) { + // if no tableSpace set, use the default tablespace USERSPACE1 + return String.format(MOVE_TABLE, tablename.toUpperCase(), "USERSPACE1", "USERSPACE1", "USERSPACE1"); + } else { + return String.format(MOVE_TABLE, tablename.toUpperCase(), tableSpace, indexSpace, lobSpace); + } + } + @Override public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns, String[] nullableColumns) { @@ -135,8 +149,13 @@ public class DB2Ddl extends PlatformDdl { @Override public String reorgTable(String table, int counter) { - // TODO Auto-generated method stub return "call sysproc.admin_cmd('reorg table " + lowerTableName(table) + "') /* reorg #" + counter + " */"; } - + + @Override + public void addTablespace(DdlBuffer apply, String tablespaceName, String indexTablespace, String lobTablespace) + throws IOException { + apply.append(" in ").append(tablespaceName).append(" index in ").append(indexTablespace).append(" long in ").append(lobTablespace); + } + } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java index ceb531530..5a292716e 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlHelp.java @@ -1,6 +1,8 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform; public class DdlHelp { + public static final String TABLESPACE_DEFAULT = "$TABLESPACE_DEFAULT"; + public static final String DROP_DEFAULT = "DROP DEFAULT"; public static final String DROP_COMMENT = "DROP COMMENT"; @@ -36,4 +38,15 @@ public class DdlHelp { public static boolean isDropForeignKey(String value) { return DROP_FOREIGN_KEY.equals(value); } + + /** + * Returns the tablespace. Returns null, if this is the special '$TABLESPACE_DEFAULT' value. + */ + public static String toTablespace(String tablespace) { + if (TABLESPACE_DEFAULT.equals(tablespace)) { + return null; + } else { + return tablespace; + } + } } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java index e4eae0be9..4e39a0b34 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -127,7 +127,7 @@ public class PlatformDdl { protected boolean inlineForeignKeys; protected boolean includeStorageEngine; - + protected final DbDefaultValue dbDefaultValue; protected String fallbackArrayType = "varchar(1000)"; @@ -400,7 +400,7 @@ public class PlatformDdl { public String dropIndex(String indexName, String tableName, boolean concurrent) { return dropIndexIfExists + maxConstraintName(indexName); } - + public String createIndex(WriteCreateIndex create) { if (create.useDefinition()) { return create.getDefinition(); @@ -508,6 +508,13 @@ public class PlatformDdl { return "alter table " + tableName + " " + dropConstraintIfExists + " " + maxConstraintName(constraintName); } + /** + * Moves the table to an other tablespace. + */ + public String alterTableTablespace(String tablename, String tableSpace, String indexSpace, String lobSpace) { + return null; + } + /** * Add a unique constraint to the table. *

@@ -772,6 +779,14 @@ public class PlatformDdl { public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) throws IOException { // only supported by postgres initially } + + /** + * Adds tablespace declaration. Now only supported for db2. + * @throws IOException + */ + public void addTablespace(DdlBuffer apply, String tablespaceName, String indexTablespace, String lobTablespace) throws IOException{ + // now only supported for db2 + } /** * Returns a statement to reorganize the table. This is required mainly for DB2. diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/AlterTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/AlterTable.java new file mode 100644 index 000000000..9e697196c --- /dev/null +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/AlterTable.java @@ -0,0 +1,526 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2022.02.01 at 12:03:38 PM CET +// + + +package io.ebeaninternal.dbmigration.migration; + +import java.math.BigInteger; +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.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for anonymous complex type. + * + *

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

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attGroup ref="{http://ebean-orm.github.io/xml/ns/dbmigration}tablespaceAttributes"/>
+ *       <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="newName" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="partitionMode" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="partitionColumn" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="identityType" type="{http://ebean-orm.github.io/xml/ns/dbmigration}identityType" />
+ *       <attribute name="identityStart" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
+ *       <attribute name="identityIncrement" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
+ *       <attribute name="identityCache" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
+ *       <attribute name="identityGenerated" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="sequenceName" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="sequenceInitial" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
+ *       <attribute name="sequenceAllocate" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
+ *       <attribute name="pkName" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="storageEngine" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "") +@XmlRootElement(name = "alterTable") +public class AlterTable { + + @XmlAttribute(name = "name", required = true) + protected String name; + @XmlAttribute(name = "newName") + protected String newName; + @XmlAttribute(name = "partitionMode") + protected String partitionMode; + @XmlAttribute(name = "partitionColumn") + protected String partitionColumn; + @XmlAttribute(name = "identityType") + protected IdentityType identityType; + @XmlAttribute(name = "identityStart") + @XmlSchemaType(name = "positiveInteger") + protected BigInteger identityStart; + @XmlAttribute(name = "identityIncrement") + @XmlSchemaType(name = "positiveInteger") + protected BigInteger identityIncrement; + @XmlAttribute(name = "identityCache") + @XmlSchemaType(name = "positiveInteger") + protected BigInteger identityCache; + @XmlAttribute(name = "identityGenerated") + protected String identityGenerated; + @XmlAttribute(name = "sequenceName") + protected String sequenceName; + @XmlAttribute(name = "sequenceInitial") + @XmlSchemaType(name = "positiveInteger") + protected BigInteger sequenceInitial; + @XmlAttribute(name = "sequenceAllocate") + @XmlSchemaType(name = "positiveInteger") + protected BigInteger sequenceAllocate; + @XmlAttribute(name = "pkName") + protected String pkName; + @XmlAttribute(name = "storageEngine") + protected String storageEngine; + @XmlAttribute(name = "tablespace") + protected String tablespace; + @XmlAttribute(name = "indexTablespace") + protected String indexTablespace; + @XmlAttribute(name = "lobTablespace") + protected String lobTablespace; + @XmlAttribute(name = "comment") + protected String comment; + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the newName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getNewName() { + return newName; + } + + /** + * Sets the value of the newName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setNewName(String value) { + this.newName = value; + } + + /** + * Gets the value of the partitionMode property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartitionMode() { + return partitionMode; + } + + /** + * Sets the value of the partitionMode property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartitionMode(String value) { + this.partitionMode = value; + } + + /** + * Gets the value of the partitionColumn property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPartitionColumn() { + return partitionColumn; + } + + /** + * Sets the value of the partitionColumn property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPartitionColumn(String value) { + this.partitionColumn = value; + } + + /** + * Gets the value of the identityType property. + * + * @return + * possible object is + * {@link IdentityType } + * + */ + public IdentityType getIdentityType() { + return identityType; + } + + /** + * Sets the value of the identityType property. + * + * @param value + * allowed object is + * {@link IdentityType } + * + */ + public void setIdentityType(IdentityType value) { + this.identityType = value; + } + + /** + * Gets the value of the identityStart property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getIdentityStart() { + return identityStart; + } + + /** + * Sets the value of the identityStart property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setIdentityStart(BigInteger value) { + this.identityStart = value; + } + + /** + * Gets the value of the identityIncrement property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getIdentityIncrement() { + return identityIncrement; + } + + /** + * Sets the value of the identityIncrement property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setIdentityIncrement(BigInteger value) { + this.identityIncrement = value; + } + + /** + * Gets the value of the identityCache property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getIdentityCache() { + return identityCache; + } + + /** + * Sets the value of the identityCache property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setIdentityCache(BigInteger value) { + this.identityCache = value; + } + + /** + * Gets the value of the identityGenerated property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getIdentityGenerated() { + return identityGenerated; + } + + /** + * Sets the value of the identityGenerated property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setIdentityGenerated(String value) { + this.identityGenerated = value; + } + + /** + * Gets the value of the sequenceName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSequenceName() { + return sequenceName; + } + + /** + * Sets the value of the sequenceName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSequenceName(String value) { + this.sequenceName = value; + } + + /** + * Gets the value of the sequenceInitial property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSequenceInitial() { + return sequenceInitial; + } + + /** + * Sets the value of the sequenceInitial property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSequenceInitial(BigInteger value) { + this.sequenceInitial = value; + } + + /** + * Gets the value of the sequenceAllocate property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getSequenceAllocate() { + return sequenceAllocate; + } + + /** + * Sets the value of the sequenceAllocate property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setSequenceAllocate(BigInteger value) { + this.sequenceAllocate = value; + } + + /** + * Gets the value of the pkName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getPkName() { + return pkName; + } + + /** + * Sets the value of the pkName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setPkName(String value) { + this.pkName = value; + } + + /** + * Gets the value of the storageEngine property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getStorageEngine() { + return storageEngine; + } + + /** + * Sets the value of the storageEngine property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setStorageEngine(String value) { + this.storageEngine = value; + } + + /** + * Gets the value of the tablespace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getTablespace() { + return tablespace; + } + + /** + * Sets the value of the tablespace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setTablespace(String value) { + this.tablespace = value; + } + + /** + * Gets the value of the indexTablespace property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getIndexTablespace() { + return indexTablespace; + } + + /** + * Sets the value of the indexTablespace property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setIndexTablespace(String value) { + this.indexTablespace = value; + } + + /** + * Gets the value of the lobTablespace property. + * + * @return possible object is + * {@link String } + */ + public String getLobTablespace() { + return lobTablespace; + } + + /** + * Sets the value of the lobTablespace property. + * + * @param value allowed object is + * {@link String } + */ + public void setLobTablespace(String value) { + this.lobTablespace = value; + } + + /** + * Gets the value of the comment property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getComment() { + return comment; + } + + /** + * Sets the value of the comment property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setComment(String value) { + this.comment = value; + } + +} diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ChangeSet.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ChangeSet.java index 5fa984ce1..68d971f37 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ChangeSet.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ChangeSet.java @@ -47,6 +47,7 @@ public class ChangeSet { @XmlElement(name = "configuration", type = Configuration.class), @XmlElement(name = "sql", type = Sql.class), @XmlElement(name = "createTable", type = CreateTable.class), + @XmlElement(name = "alterTable", type = AlterTable.class), @XmlElement(name = "dropTable", type = DropTable.class), @XmlElement(name = "renameTable", type = RenameTable.class), @XmlElement(name = "addTableComment", type = AddTableComment.class), diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/CreateTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/CreateTable.java index 8c451d2ec..da87ee195 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/CreateTable.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/CreateTable.java @@ -99,6 +99,8 @@ public class CreateTable { protected String tablespace; @XmlAttribute(name = "indexTablespace") protected String indexTablespace; + @XmlAttribute(name = "lobTablespace") + protected String lobTablespace; @XmlAttribute(name = "comment") protected String comment; @@ -522,6 +524,26 @@ public class CreateTable { public void setIndexTablespace(String value) { this.indexTablespace = value; } + + /** + * Gets the value of the lobTablespace property. + * + * @return possible object is + * {@link String } + */ + public String getLobTablespace() { + return lobTablespace; + } + + /** + * Sets the value of the lobTablespace property. + * + * @param value allowed object is + * {@link String } + */ + public void setLobTablespace(String value) { + this.lobTablespace = value; + } /** * Gets the value of the comment property. diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ObjectFactory.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ObjectFactory.java index ac15ca0d5..0fb3cec99 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ObjectFactory.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/migration/ObjectFactory.java @@ -187,6 +187,14 @@ public class ObjectFactory { return new ChangeSet(); } + /** + * Create an instance of {@link AlterTable } + * + */ + public AlterTable createAlterTable() { + return new AlterTable(); + } + /** * Create an instance of {@link AddHistoryTable } */ diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java index 90fd27228..fe54e0814 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/MTable.java @@ -5,6 +5,7 @@ import io.ebeaninternal.dbmigration.migration.AddColumn; import io.ebeaninternal.dbmigration.migration.AddHistoryTable; import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AlterColumn; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.Column; import io.ebeaninternal.dbmigration.migration.CreateTable; import io.ebeaninternal.dbmigration.migration.DropColumn; @@ -17,6 +18,8 @@ import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.IdentityMode; import io.ebeaninternal.server.deploy.PartitionMeta; +import io.ebeaninternal.server.deploy.TablespaceMeta; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,6 +29,7 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import static io.ebeaninternal.dbmigration.ddlgeneration.platform.SplitColumns.split; @@ -56,11 +60,10 @@ public class MTable { */ private boolean draft; private PartitionMeta partitionMeta; + private TablespaceMeta tablespaceMeta; private String pkName; private String comment; - private String tablespace; private String storageEngine; - private String indexTablespace; private IdentityMode identityMode; private boolean withHistory; private final Map columns = new LinkedHashMap<>(); @@ -93,6 +96,7 @@ public class MTable { this.identityMode = descriptor.identityMode(); this.storageEngine = descriptor.storageEngine(); this.partitionMeta = descriptor.partitionMeta(); + this.tablespaceMeta = descriptor.tablespaceMeta(); this.comment = descriptor.dbComment(); if (descriptor.isHistorySupport()) { withHistory = true; @@ -104,11 +108,28 @@ public class MTable { } /** - * Construct for element collection or intersection table. + * Constructor for test cases only! */ + @Deprecated public MTable(String name) { + this(name, null, null); + } + + /** + * Construct for element collection or intersection table. They have same table space and storage engine. + */ + public MTable(String name, BeanDescriptor descriptor) { + this(name, descriptor.tablespaceMeta(), descriptor.storageEngine()); + } + + /** + * Constructor for dependant tables (draft/element collection or intersection). + */ + private MTable(String name, TablespaceMeta tablespaceMeta, String storageEngine) { this.name = name; this.identityMode = IdentityMode.NONE; + this.tablespaceMeta = tablespaceMeta; + this.storageEngine = storageEngine; } /** @@ -118,7 +139,7 @@ public class MTable { * later when creating the CreateTable object. */ public MTable createDraftTable() { - draftTable = new MTable(name + "_draft"); + draftTable = new MTable(name + "_draft", this.tablespaceMeta, this.storageEngine); draftTable.draft = true; draftTable.whenCreatedColumn = whenCreatedColumn; // compoundKeys @@ -138,8 +159,13 @@ public class MTable { this.pkName = createTable.getPkName(); this.comment = createTable.getComment(); this.storageEngine = createTable.getStorageEngine(); - this.tablespace = createTable.getTablespace(); - this.indexTablespace = createTable.getIndexTablespace(); + if (createTable.getTablespace() != null) { + this.tablespaceMeta = new TablespaceMeta(createTable.getTablespace(), + createTable.getIndexTablespace() != null ? createTable.getIndexTablespace() : createTable.getTablespace(), + createTable.getLobTablespace() != null ? createTable.getLobTablespace() : createTable.getTablespace()); + } else { + this.tablespaceMeta = null; + } this.withHistory = Boolean.TRUE.equals(createTable.isWithHistory()); this.draft = Boolean.TRUE.equals(createTable.isDraft()); this.identityMode = fromCreateTable(createTable); @@ -210,8 +236,11 @@ public class MTable { createTable.setPartitionColumn(partitionMeta.getProperty()); } createTable.setStorageEngine(storageEngine); - createTable.setTablespace(tablespace); - createTable.setIndexTablespace(indexTablespace); + if (tablespaceMeta != null) { + createTable.setTablespace(tablespaceMeta.getTablespaceName()); + createTable.setIndexTablespace(tablespaceMeta.getIndexTablespace()); + createTable.setLobTablespace(tablespaceMeta.getLobTablespace()); + } toCreateTable(identityMode, createTable); if (withHistory) { createTable.setWithHistory(Boolean.TRUE); @@ -266,6 +295,8 @@ public class MTable { compareCompoundKeys(modelDiff, newTable); compareUniqueKeys(modelDiff, newTable); + compareTableAttrs(modelDiff, newTable); + } private void compareColumns(ModelDiff modelDiff, MTable newTable) { @@ -335,6 +366,29 @@ public class MTable { modelDiff.addUniqueConstraint(newKey.addUniqueConstraint(name)); } } + + private void compareTableAttrs(ModelDiff modelDiff, MTable newTable) { + AlterTable alterTable = new AlterTable(); + alterTable.setName(newTable.getName()); + boolean altered = false; + + if (!Objects.equals(tablespaceMeta, newTable.getTablespaceMeta())) { + if (newTable.getTablespaceMeta() == null) { + alterTable.setTablespace(DdlHelp.TABLESPACE_DEFAULT); + alterTable.setIndexTablespace(DdlHelp.TABLESPACE_DEFAULT); + alterTable.setLobTablespace(DdlHelp.TABLESPACE_DEFAULT); + } else { + alterTable.setTablespace(newTable.getTablespaceMeta().getTablespaceName()); + alterTable.setIndexTablespace(newTable.getTablespaceMeta().getIndexTablespace()); + alterTable.setLobTablespace(newTable.getTablespaceMeta().getLobTablespace()); + } + altered = true; + } + + if (altered) { + modelDiff.addAlterTable(alterTable); + } + } /** * Apply AddColumn migration. @@ -424,13 +478,13 @@ public class MTable { public void setComment(String comment) { this.comment = comment; } - - public String getTablespace() { - return tablespace; + + public void setTablespaceMeta(TablespaceMeta tablespaceMeta) { + this.tablespaceMeta = tablespaceMeta; } - - public String getIndexTablespace() { - return indexTablespace; + + public TablespaceMeta getTablespaceMeta() { + return tablespaceMeta; } public boolean isWithHistory() { diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelContainer.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelContainer.java index dc19ef137..9e5749483 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelContainer.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelContainer.java @@ -8,6 +8,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.ChangeSet; import io.ebeaninternal.dbmigration.migration.ChangeSetType; import io.ebeaninternal.dbmigration.migration.CreateIndex; @@ -19,6 +20,7 @@ import io.ebeaninternal.dbmigration.migration.DropTable; import io.ebeaninternal.dbmigration.migration.Migration; import io.ebeaninternal.dbmigration.migration.RenameColumn; import io.ebeaninternal.dbmigration.migration.Sql; +import io.ebeaninternal.server.deploy.TablespaceMeta; import java.util.ArrayList; import java.util.Collection; @@ -155,6 +157,8 @@ public class ModelContainer { applyChange((CreateTable) change); } else if (change instanceof DropTable) { applyChange((DropTable) change); + } else if (change instanceof AlterTable) { + applyChange((AlterTable) change); } else if (change instanceof AlterColumn) { applyChange((AlterColumn) change); } else if (change instanceof AddColumn) { @@ -261,6 +265,32 @@ public class ModelContainer { protected void applyChange(DropTable dropTable) { tables.remove(dropTable.getName()); } + + + protected void applyChange(AlterTable alterTable) { + MTable table = getTable(alterTable.getName()); + if (table == null) { + throw new IllegalStateException("Table [" + alterTable.getName() + "] does not exist in model?"); + } + // Handle Tablespace change + TablespaceMeta ts = table.getTablespaceMeta(); + + if (alterTable.getTablespace() != null) { + String currentTableSpace = DdlHelp.toTablespace(alterTable.getTablespace()); + String currentIndexSpace = DdlHelp.toTablespace(alterTable.getIndexTablespace()); + String currentLobSpace = DdlHelp.toTablespace(alterTable.getLobTablespace()); + + if (currentTableSpace != null) { + assert currentIndexSpace != null; + assert currentLobSpace != null; + table.setTablespaceMeta(new TablespaceMeta(currentTableSpace, currentIndexSpace, currentLobSpace)); + } else { + assert currentIndexSpace == null; + assert currentLobSpace == null; + table.setTablespaceMeta(null); + } + } + } /** * Apply a CreateTable change to the model. diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelDiff.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelDiff.java index 367c13ca5..9bf5cf0d0 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelDiff.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/ModelDiff.java @@ -6,6 +6,7 @@ import io.ebeaninternal.dbmigration.migration.AddTableComment; import io.ebeaninternal.dbmigration.migration.AddUniqueConstraint; import io.ebeaninternal.dbmigration.migration.AlterColumn; import io.ebeaninternal.dbmigration.migration.AlterForeignKey; +import io.ebeaninternal.dbmigration.migration.AlterTable; import io.ebeaninternal.dbmigration.migration.ChangeSet; import io.ebeaninternal.dbmigration.migration.ChangeSetType; import io.ebeaninternal.dbmigration.migration.CreateIndex; @@ -252,4 +253,11 @@ public class ModelDiff { public void addAlterForeignKey(AlterForeignKey alterForeignKey) { applyChanges.add(alterForeignKey); } + + /** + * Adds a table alter. + */ + public void addAlterTable(AlterTable alterTable) { + applyChanges.add(alterTable); + } } diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildElementTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildElementTable.java index a8a4d944e..210ac57bc 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildElementTable.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildElementTable.java @@ -18,7 +18,7 @@ public class ModelBuildElementTable { BeanTable beanTable = manyProp.beanTable(); BeanDescriptor targetDescriptor = manyProp.targetDescriptor(); - MTable table = new MTable(beanTable.getBaseTable()); + MTable table = new MTable(beanTable.getBaseTable(), manyProp.descriptor()); VisitProperties.visit(targetDescriptor, new ModelBuildPropertyVisitor(ctx, table, targetDescriptor)); ctx.addTableElementCollection(table); diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildIntersectionTable.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildIntersectionTable.java index 179de2ef8..763016278 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildIntersectionTable.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildIntersectionTable.java @@ -62,7 +62,7 @@ class ModelBuildIntersectionTable { BeanDescriptor targetDesc = manyProp.targetDescriptor(); String tableName = intersectionTableJoin.getTable(); - MTable table = new MTable(tableName); + MTable table = new MTable(tableName, localDesc); if (!manyProp.isExcludedFromHistory()) { if (localDesc.isHistorySupport()) { table.setWithHistory(true); diff --git a/ebean-ddl-generator/src/main/resources/ebean-dbmigration-1.0.xsd b/ebean-ddl-generator/src/main/resources/ebean-dbmigration-1.0.xsd index 27fc52cfa..e7ef14be7 100644 --- a/ebean-ddl-generator/src/main/resources/ebean-dbmigration-1.0.xsd +++ b/ebean-ddl-generator/src/main/resources/ebean-dbmigration-1.0.xsd @@ -218,6 +218,27 @@ + + + + + + + + + + + + + + + + + + + + + @@ -341,6 +362,7 @@ + @@ -351,6 +373,7 @@ + diff --git a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_CreateIndexTest.java b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_CreateIndexTest.java index 6886c4abb..73156d0a7 100644 --- a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_CreateIndexTest.java +++ b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl_CreateIndexTest.java @@ -109,4 +109,12 @@ public class PlatformDdl_CreateIndexTest { assertEquals("create index ix_mytab_acol on mytab (acol)", sql); } + @Test + public void db2luw_tablespaceIndex() { + String sql = db2LuwDdl.createIndex(new WriteCreateIndex("ix_mytab_acol", "mytab", new String[]{"acol"}, false)); + assertEquals("create index ix_mytab_acol on mytab (acol)", sql); + sql = db2LuwDdl.createIndex(new WriteCreateIndex("ix_mytab_acol", "mytab", new String[]{"acol"}, true)); + assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql); + } + } diff --git a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/ModelContainerApplyTest.java b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/ModelContainerApplyTest.java index da493f9ef..0d9504efb 100644 --- a/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/ModelContainerApplyTest.java +++ b/ebean-ddl-generator/src/test/java/io/ebeaninternal/dbmigration/model/ModelContainerApplyTest.java @@ -34,8 +34,8 @@ public class ModelContainerApplyTest { MTable foo = model.getTable("foo"); assertThat(foo.getComment()).isEqualTo("comment"); - assertThat(foo.getTablespace()).isEqualTo("fooSpace"); - assertThat(foo.getIndexTablespace()).isEqualTo("fooIndexSpace"); + assertThat(foo.getTablespaceMeta().getTablespaceName()).isEqualTo("fooSpace"); + assertThat(foo.getTablespaceMeta().getIndexTablespace()).isEqualTo("fooIndexSpace"); assertThat(foo.isWithHistory()).isEqualTo(false); assertThat(foo.allColumns()).extracting("name").contains("col1", "col3", "added_to_foo"); } diff --git a/ebean-ddl-generator/src/test/resources/application-test.properties b/ebean-ddl-generator/src/test/resources/application-test.properties index 5e34d4b67..af973bb3a 100644 --- a/ebean-ddl-generator/src/test/resources/application-test.properties +++ b/ebean-ddl-generator/src/test/resources/application-test.properties @@ -14,5 +14,3 @@ datasource.db2.url=jdbc:db2://localhost:50005/migtest datasource.pg.username=sa datasource.pg.password= datasource.pg.url=jdbc:h2:mem:h2AutoTune - - diff --git a/ebean-test/src/test/java/io/ebeaninternal/dbmigration/DbMigrationTest.java b/ebean-test/src/test/java/io/ebeaninternal/dbmigration/DbMigrationTest.java index 064e16b82..282e90d3f 100644 --- a/ebean-test/src/test/java/io/ebeaninternal/dbmigration/DbMigrationTest.java +++ b/ebean-test/src/test/java/io/ebeaninternal/dbmigration/DbMigrationTest.java @@ -74,6 +74,10 @@ public class DbMigrationTest extends BaseTestCase { if (isSqlServer() || isMariaDB()) { // || isMySql() runScript("I__create_procs.sql"); } + + if(isDb2()) { + runScript("I__create_tablespaces.sql"); + } runScript("1.0__initial.sql"); diff --git a/ebean-test/src/test/java/misc/migration/v1_0/EBasic.java b/ebean-test/src/test/java/misc/migration/v1_0/EBasic.java index 6e895a2f1..d43ae7292 100644 --- a/ebean-test/src/test/java/misc/migration/v1_0/EBasic.java +++ b/ebean-test/src/test/java/misc/migration/v1_0/EBasic.java @@ -4,6 +4,7 @@ import io.ebean.annotation.DbDefault; import io.ebean.annotation.EnumValue; import io.ebean.annotation.Index; import io.ebean.annotation.NotNull; +import io.ebean.annotation.Tablespace; import javax.persistence.Entity; import javax.persistence.Id; @@ -14,6 +15,7 @@ import java.sql.Timestamp; @Entity @Table(name = "migtest_e_basic") +@Tablespace(value = "TSTABLES", index = "INDEXTS") public class EBasic { public enum Status { diff --git a/ebean-test/src/test/java/misc/migration/v1_1/MtmChild.java b/ebean-test/src/test/java/misc/migration/v1_1/MtmChild.java index bdcd43845..1a76b7249 100644 --- a/ebean-test/src/test/java/misc/migration/v1_1/MtmChild.java +++ b/ebean-test/src/test/java/misc/migration/v1_1/MtmChild.java @@ -4,10 +4,14 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.Table; + +import io.ebean.annotation.Tablespace; + import java.util.List; @Entity @Table(name = "migtest_mtm_c") +@Tablespace("TESTTS") public class MtmChild { @Id diff --git a/ebean-test/src/test/java/misc/migration/v1_1/MtmMaster.java b/ebean-test/src/test/java/misc/migration/v1_1/MtmMaster.java index de0f3ffc9..977b38188 100644 --- a/ebean-test/src/test/java/misc/migration/v1_1/MtmMaster.java +++ b/ebean-test/src/test/java/misc/migration/v1_1/MtmMaster.java @@ -5,10 +5,14 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.Table; + +import io.ebean.annotation.Tablespace; + import java.util.List; @Entity @Table(name = "migtest_mtm_m") +@Tablespace("TSMASTER") public class MtmMaster { @Id diff --git a/ebean-test/src/test/java/org/tests/compositekeys/TestOnCascadeDeleteChildrenWithCompositeKeys.java b/ebean-test/src/test/java/org/tests/compositekeys/TestOnCascadeDeleteChildrenWithCompositeKeys.java index dbcaf4b0d..fe904adfb 100644 --- a/ebean-test/src/test/java/org/tests/compositekeys/TestOnCascadeDeleteChildrenWithCompositeKeys.java +++ b/ebean-test/src/test/java/org/tests/compositekeys/TestOnCascadeDeleteChildrenWithCompositeKeys.java @@ -5,7 +5,6 @@ import io.ebean.CountDistinctOrder; import io.ebean.DB; import io.ebean.Query; import io.ebean.annotation.Identity; -import io.ebean.annotation.Platform; import io.ebeaninternal.api.SpiEbeanServer; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; diff --git a/ebean-test/src/test/resources/extra-ddl.xml b/ebean-test/src/test/resources/extra-ddl.xml index f93a47acd..9c76745db 100644 --- a/ebean-test/src/test/resources/extra-ddl.xml +++ b/ebean-test/src/test/resources/extra-ddl.xml @@ -72,5 +72,36 @@ call SYSPROC.SYSINSTALLOBJECTS( 'EXPLAIN', 'C' , '', CURRENT SCHEMA ); END IF; END;$$ + + +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TSTABLES')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TSTABLES"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'INDEXTS')) +THEN EXECUTE IMMEDIATE 'CREATE TABLESPACE "INDEXTS"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TESTTS')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TESTTS"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TSMASTER')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TSMASTER"'; +END IF; +END +$$ + diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.0__initial.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.0__initial.sql index 5d4113a24..ee7de7978 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.0__initial.sql +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.0__initial.sql @@ -74,7 +74,7 @@ create table migtest_e_basic ( constraint ck_migtest_e_basic_status check ( status in ('N','A','I')), constraint ck_migtest_e_basic_status2 check ( status2 in ('N','A','I')), constraint pk_migtest_e_basic primary key (id) -); +) in TSTABLES index in INDEXTS long in TSTABLES; create unique index uq_migtest_e_basic_indextest2 on migtest_e_basic(indextest2) exclude null keys; create unique index uq_migtest_e_basic_indextest6 on migtest_e_basic(indextest6) exclude null keys; diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.1.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.1.sql index be4855727..720360470 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.1.sql +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.1.sql @@ -9,18 +9,18 @@ create table migtest_mtm_c_migtest_mtm_m ( migtest_mtm_c_id integer not null, migtest_mtm_m_id bigint not null, constraint pk_migtest_mtm_c_migtest_mtm_m primary key (migtest_mtm_c_id,migtest_mtm_m_id) -); +) in TESTTS index in TESTTS long in TESTTS; create table migtest_mtm_m_migtest_mtm_c ( migtest_mtm_m_id bigint not null, migtest_mtm_c_id integer not null, constraint pk_migtest_mtm_m_migtest_mtm_c primary key (migtest_mtm_m_id,migtest_mtm_c_id) -); +) in TSMASTER index in TSMASTER long in TSMASTER; create table migtest_mtm_m_phone_numbers ( migtest_mtm_m_id bigint not null, value varchar(255) not null -); +) in TSMASTER index in TSMASTER long in TSMASTER; alter table migtest_ckey_detail add column one_key integer; alter table migtest_ckey_detail add column two_key varchar(127); @@ -119,6 +119,7 @@ create unique index uq_migtest_e_basic_status_indextest1 on migtest_e_basic(stat create unique index uq_migtest_e_basic_name on migtest_e_basic(name) exclude null keys; create unique index uq_migtest_e_basic_indextest4 on migtest_e_basic(indextest4) exclude null keys; create unique index uq_migtest_e_basic_indextest5 on migtest_e_basic(indextest5) exclude null keys; +CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'MIGTEST_E_BASIC','USERSPACE1','USERSPACE1','USERSPACE1','','','','','','MOVE'); delimiter $$ begin if exists (select constname from syscat.tabconst where tabschema = current_schema and constname = 'CK_MIGTEST_E_ENUM_TEST_STATUS' and tabname = 'MIGTEST_E_ENUM') then @@ -152,6 +153,8 @@ alter table migtest_e_history6 alter column test_number1 set not null; alter table migtest_e_history6 alter column test_number2 drop not null; alter table migtest_e_softdelete add column deleted boolean default false not null; +CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'MIGTEST_MTM_C','TESTTS','TESTTS','TESTTS','','','','','','MOVE'); +CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'MIGTEST_MTM_M','TSMASTER','TSMASTER','TSMASTER','','','','','','MOVE'); alter table migtest_oto_child add column master_id bigint; call sysproc.admin_cmd('reorg table migtest_e_history6') /* reorg #6 */; diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.3.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.3.sql index 4b5fdcf13..597876255 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.3.sql +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/1.3.sql @@ -183,6 +183,8 @@ call sysproc.admin_cmd('reorg table migtest_e_history4') /* reorg #6 */; update migtest_e_history6 set test_number2 = 7 where test_number2 is null; alter table migtest_e_history6 alter column test_number2 set default 7; alter table migtest_e_history6 alter column test_number2 set not null; +CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'MIGTEST_MTM_C','USERSPACE1','USERSPACE1','USERSPACE1','','','','','','MOVE'); +CALL SYSPROC.ADMIN_MOVE_TABLE(CURRENT_SCHEMA,'MIGTEST_MTM_M','USERSPACE1','USERSPACE1','USERSPACE1','','','','','','MOVE'); call sysproc.admin_cmd('reorg table migtest_e_history6') /* reorg #7 */; 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/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/I__create_tablespaces.sql b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/I__create_tablespaces.sql new file mode 100644 index 000000000..e118fc1a1 --- /dev/null +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/I__create_tablespaces.sql @@ -0,0 +1,29 @@ + +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TSTABLES')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TSTABLES"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'INDEXTS')) +THEN EXECUTE IMMEDIATE 'CREATE TABLESPACE "INDEXTS"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TESTTS')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TESTTS"'; +END IF; +END +$$ +delimiter $$ +BEGIN +IF (NOT exists (SELECT * FROM SYSIBM.SYSTABLESPACES WHERE TBSPACE = 'TSMASTER')) THEN +EXECUTE IMMEDIATE 'CREATE TABLESPACE "TSMASTER"'; +END IF; +END +$$ diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/idx_db2.migrations b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/idx_db2.migrations index a83d329f0..ea4916d39 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/idx_db2.migrations +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/db2luw/idx_db2.migrations @@ -1,7 +1,8 @@ -1580812656, 1.0__initial.sql --2144208808, 1.1.sql +-1602289007, I__create_tablespaces.sql +999346633, 1.0__initial.sql +2079409430, 1.1.sql 1091886546, 1.2__dropsFor_1.1.sql --1041850370, 1.3.sql +-1291483335, 1.3.sql 1293885677, 1.4__dropsFor_1.3.sql -133543359, R__db2_explain_tables.sql 561281075, R__order_views.sql diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.0__initial.model.xml b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.0__initial.model.xml index 68661ce4c..daeab815e 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.0__initial.model.xml +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.0__initial.model.xml @@ -37,7 +37,7 @@ - + diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.1.model.xml b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.1.model.xml index 7754adc51..c4692737c 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.1.model.xml +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.1.model.xml @@ -46,6 +46,7 @@ + @@ -81,19 +82,21 @@ - + + - + + - + diff --git a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.3.model.xml b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.3.model.xml index 296b101b0..c6b567592 100644 --- a/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.3.model.xml +++ b/ebean-test/src/test/resources/migrationtest/dbmigration/model/1.3.model.xml @@ -38,6 +38,8 @@ + + diff --git a/ebean-test/testconfig/ebean-db2.properties b/ebean-test/testconfig/ebean-db2.properties index 40e375ef5..4ffab60f1 100644 --- a/ebean-test/testconfig/ebean-db2.properties +++ b/ebean-test/testconfig/ebean-db2.properties @@ -1,5 +1,7 @@ ebean.test.platform=db2 ebean.test.dbName=unit -ebean.test.dbPassword=unit +# we need admin user to call the procedure SYSPROC.ADMIN_MOVE_TABLE +ebean.test.username=admin +ebean.test.password=admin datasource.default=db2-11 ebean.db2-11.databasePlatformName=db2luw diff --git a/release.md b/release.md index 944b41b9f..f378a29e5 100644 --- a/release.md +++ b/release.md @@ -4,3 +4,8 @@ We @foconis use this command to release. mvn versions:set -DgenerateBackupPoms=false -DnewVersion=12.14.2-FOC1-SNAPSHOT mvn release:prepare release:perform -Darguments="-Dgpg.skip -DskipTests" + +generate Java classes from .xsd: + + export JAVA_TOOL_OPTIONS="-Duser.language=en -Duser.country=US -Dfile.encoding=UTF-8" + /c/Program\ Files/Java/jdk1.8.0_201/bin/xjc.exe src/main/resources/ebean-dbmigration-1.0.xsd -d src/main/java -p io.ebeaninternal.dbmigration.migration