From bfc2b57df5ea5fa5f466e8e8792af0f67997ff77 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Wed, 4 Mar 2020 21:29:56 +1300 Subject: [PATCH] Support for @Identity - use identity options with sequence --- .../ddlgeneration/platform/BaseTableDdl.java | 35 +++++++-------- .../ddlgeneration/platform/DdlIdentity.java | 38 ++++++++++++++-- .../ddlgeneration/platform/PlatformDdl.java | 15 +++---- .../ddlgeneration/platform/SqlServerDdl.java | 24 +++++----- .../org/tests/query/TestQueryFilterMany.java | 4 +- .../sqlserver17/1.0__initial.sql | 44 +++++++++---------- .../migrationtest/sqlserver17/1.1.sql | 2 +- .../migrationtest/sqlserver17/1.3.sql | 2 +- src/test/resources/ebean.properties | 2 +- 9 files changed, 98 insertions(+), 68 deletions(-) diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java index aed55af17..c707b92e6 100644 --- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java +++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/BaseTableDdl.java @@ -248,18 +248,19 @@ public class BaseTableDdl implements TableDdl { List columns = createTable.getColumn(); List pk = determinePrimaryKeyColumns(columns); - DdlIdentity idMode = DdlIdentity.NONE; + DdlIdentity identity = DdlIdentity.NONE; if ((pk.size() == 1)) { final IdentityMode identityMode = MTableIdentity.fromCreateTable(createTable); IdType idType = platformDdl.useIdentityType(identityMode.getIdType()); - idMode = new DdlIdentity(idType, identityMode); + String sequenceName = (IdType.SEQUENCE != idType) ? null : sequenceName(createTable, pk, identity); + identity = new DdlIdentity(idType, identityMode, sequenceName); } String partitionMode = createTable.getPartitionMode(); DdlBuffer apply = writer.apply(); apply.append(platformDdl.getCreateTableCommandPrefix()).append(" ").append(tableName).append(" ("); - writeTableColumns(apply, columns, idMode); + writeTableColumns(apply, columns, identity); writeUniqueConstraints(apply, createTable); writeCompoundUniqueConstraints(apply, createTable); if (!pk.isEmpty()) { @@ -294,9 +295,8 @@ public class BaseTableDdl implements TableDdl { // we drop the related sequence (if sequences are used) dropTable(writer.dropAll(), tableName); - if (idMode.useSequence()) { - String pkCol = pk.get(0).getName(); - writeSequence(writer, createTable, pkCol); + if (identity.useSequence()) { + writeSequence(writer, identity); } // add blank line for a bit of whitespace between tables @@ -308,6 +308,14 @@ public class BaseTableDdl implements TableDdl { } } + private String sequenceName(CreateTable createTable, List pk, DdlIdentity identity) { + String seqName = identity.getSequenceName(); + if (seqName == null || seqName.isEmpty()) { + seqName = namingConvention.getSequenceName(createTable.getName(), pk.get(0).getName()); + } + return seqName; + } + /** * Add table and column comments (separate from the create table statement). */ @@ -377,18 +385,9 @@ public class BaseTableDdl implements TableDdl { } } - protected void writeSequence(DdlWrite writer, CreateTable createTable, String pk) throws IOException { - // explicit sequence use or platform decides - String explicitSequenceName = createTable.getSequenceName(); - int initial = toInt(createTable.getSequenceInitial()); - int allocate = toInt(createTable.getSequenceAllocate()); - - String seqName = explicitSequenceName; - if (seqName == null || seqName.isEmpty()) { - seqName = namingConvention.getSequenceName(createTable.getName(), pk); - } - - String createSeq = platformDdl.createSequence(seqName, initial, allocate); + protected void writeSequence(DdlWrite writer, DdlIdentity identity) throws IOException { + String seqName = identity.getSequenceName(); + String createSeq = platformDdl.createSequence(seqName, identity); if (hasValue(createSeq)) { writer.apply().append(createSeq).newLine(); writer.dropAll().appendStatement(platformDdl.dropSequence(seqName)); diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlIdentity.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlIdentity.java index 3ecc46361..bf9c2fcc5 100644 --- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlIdentity.java +++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/DdlIdentity.java @@ -10,15 +10,18 @@ public class DdlIdentity { private final IdType idType; private final IdentityMode identityMode; + private final String sequenceName; - public DdlIdentity(IdType idType, IdentityMode identityMode) { + public DdlIdentity(IdType idType, IdentityMode identityMode, String sequenceName) { this.idType = idType; this.identityMode = identityMode; + this.sequenceName = sequenceName; } private DdlIdentity() { this.idType = null; this.identityMode = null; + this.sequenceName = null; } public boolean useSequence() { @@ -29,6 +32,10 @@ public class DdlIdentity { return idType == IdType.IDENTITY; } + public String getSequenceName() { + return sequenceName; + } + private String generatedBy() { return isAlways() ? "always" : "by default"; } @@ -41,16 +48,28 @@ public class DdlIdentity { return " generated " + generatedBy() +" as identity"; } - public String options(String startWith, String incrementBy, String cache) { + public String identityOptions(String startWith, String incrementBy, String cache) { + return options(true, startWith, incrementBy, cache); + } + + public String sequenceOptions(String startWith, String incrementBy, String cache) { + return options(false, startWith, incrementBy, cache); + } + + private String options(boolean brackets, String startWith, String incrementBy, String cache) { if (!identityMode.hasOptions()) { return ""; } StringBuilder sb = new StringBuilder(40); - sb.append(" ("); + if (brackets) { + sb.append(" ("); + } optionFor(sb, startWith, identityMode.getStart()); optionFor(sb, incrementBy, identityMode.getIncrement()); optionFor(sb, cache, identityMode.getCache()); - sb.append(")"); + if (brackets) { + sb.append(")"); + } return sb.toString(); } @@ -63,4 +82,15 @@ public class DdlIdentity { } } + public int getStart() { + return identityMode.getStart(); + } + + public int getIncrement() { + return identityMode.getIncrement(); + } + + public int getCache() { + return identityMode.getCache(); + } } diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java index 3580d224b..1b893db93 100644 --- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java +++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java @@ -68,6 +68,9 @@ public class PlatformDdl { protected String identityStartWith = "start with"; protected String identityIncrementBy = "increment by"; protected String identityCache = "cache"; + protected String sequenceStartWith = "start with"; + protected String sequenceIncrementBy = "increment by"; + protected String sequenceCache = "cache"; protected String alterTableIfExists = ""; @@ -195,7 +198,7 @@ public class PlatformDdl { StringBuilder sb = new StringBuilder(columnDefn.length() + 60); sb.append(columnDefn).append(identity.optionGenerated()); - sb.append(identity.options(identityStartWith, identityIncrementBy, identityCache)); + sb.append(identity.identityOptions(identityStartWith, identityIncrementBy, identityCache)); return sb.toString(); } @@ -362,16 +365,10 @@ public class PlatformDdl { /** * Generate and return the create sequence DDL. */ - public String createSequence(String sequenceName, int initialValue, int allocationSize) { - + public String createSequence(String sequenceName, DdlIdentity identity) { StringBuilder sb = new StringBuilder("create sequence "); sb.append(sequenceName); - if (initialValue > 1) { - sb.append(" start with ").append(initialValue); - } - if (allocationSize > 1) { - sb.append(" increment by ").append(allocationSize); - } + identity.sequenceOptions(sequenceStartWith, sequenceIncrementBy, sequenceCache); sb.append(";"); return sb.toString(); } diff --git a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java index 027031f20..4018b0fab 100644 --- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java +++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java @@ -114,18 +114,22 @@ public class SqlServerDdl extends PlatformDdl { * Generate and return the create sequence DDL. */ @Override - public String createSequence(String sequenceName, int initialValue, int allocationSize) { - - StringBuilder sb = new StringBuilder("create sequence "); - sb.append(sequenceName); - sb.append(" as bigint "); - if (initialValue > 1) { - sb.append(" start with ").append(initialValue); + public String createSequence(String sequenceName, DdlIdentity identity) { + StringBuilder sb = new StringBuilder(80); + sb.append("create sequence ").append(sequenceName).append(" as bigint"); + final int start = identity.getStart(); + if (start > 1) { + sb.append(" start with ").append(start); } else { - sb.append(" start with 1 "); + sb.append(" start with 1"); } - if (allocationSize > 1) { - sb.append(" increment by ").append(allocationSize); + final int increment = identity.getIncrement(); + if (increment > 1) { + sb.append(" increment by ").append(increment); + } + final int cache = identity.getCache(); + if (cache > 1) { + sb.append(" cache ").append(increment); } sb.append(";"); return sb.toString(); diff --git a/src/test/java/org/tests/query/TestQueryFilterMany.java b/src/test/java/org/tests/query/TestQueryFilterMany.java index 3132c2381..2e031fbf2 100644 --- a/src/test/java/org/tests/query/TestQueryFilterMany.java +++ b/src/test/java/org/tests/query/TestQueryFilterMany.java @@ -56,7 +56,7 @@ public class TestQueryFilterMany extends BaseTestCase { final Query query = DB.find(Customer.class) .where().ieq("name", "Rob") // fluid style adding maxRows/firstRow to filterMany - .filterMany("orders").eq("status", Order.Status.NEW).setMaxRows(100).setFirstRow(3) + .filterMany("orders").eq("status", Order.Status.NEW).order("id desc").setMaxRows(100).setFirstRow(3) .order().asc("id").setMaxRows(5); final List customers = query.findList(); @@ -86,7 +86,7 @@ public class TestQueryFilterMany extends BaseTestCase { .order().asc("id").setMaxRows(5); // non-fluid style adding maxRows/firstRow - final ExpressionList filterMany = query.filterMany("orders").eq("status", Order.Status.NEW); + final ExpressionList filterMany = query.filterMany("orders").order("id desc").eq("status", Order.Status.NEW); filterMany.setMaxRows(100); filterMany.setFirstRow(3); diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver17/1.0__initial.sql b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.0__initial.sql index 545c2161d..af322b975 100644 --- a/src/test/resources/dbmigration/migrationtest/sqlserver17/1.0__initial.sql +++ b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.0__initial.sql @@ -5,14 +5,14 @@ create table migtest_ckey_assoc ( assoc_one nvarchar(255), constraint pk_migtest_ckey_assoc primary key (id) ); -create sequence migtest_ckey_assoc_seq as bigint start with 1 ; +create sequence migtest_ckey_assoc_seq as bigint start with 1; create table migtest_ckey_detail ( id integer not null, something nvarchar(255), constraint pk_migtest_ckey_detail primary key (id) ); -create sequence migtest_ckey_detail_seq as bigint start with 1 ; +create sequence migtest_ckey_detail_seq as bigint start with 1; create table migtest_ckey_parent ( one_key integer not null, @@ -27,40 +27,40 @@ create table migtest_fk_cascade ( one_id numeric(19), constraint pk_migtest_fk_cascade primary key (id) ); -create sequence migtest_fk_cascade_seq as bigint start with 1 ; +create sequence migtest_fk_cascade_seq as bigint start with 1; create table migtest_fk_cascade_one ( id numeric(19) not null, constraint pk_migtest_fk_cascade_one primary key (id) ); -create sequence migtest_fk_cascade_one_seq as bigint start with 1 ; +create sequence migtest_fk_cascade_one_seq as bigint start with 1; create table migtest_fk_none ( id numeric(19) not null, one_id numeric(19), constraint pk_migtest_fk_none primary key (id) ); -create sequence migtest_fk_none_seq as bigint start with 1 ; +create sequence migtest_fk_none_seq as bigint start with 1; create table migtest_fk_none_via_join ( id numeric(19) not null, one_id numeric(19), constraint pk_migtest_fk_none_via_join primary key (id) ); -create sequence migtest_fk_none_via_join_seq as bigint start with 1 ; +create sequence migtest_fk_none_via_join_seq as bigint start with 1; create table migtest_fk_one ( id numeric(19) not null, constraint pk_migtest_fk_one primary key (id) ); -create sequence migtest_fk_one_seq as bigint start with 1 ; +create sequence migtest_fk_one_seq as bigint start with 1; create table migtest_fk_set_null ( id numeric(19) not null, one_id numeric(19), constraint pk_migtest_fk_set_null primary key (id) ); -create sequence migtest_fk_set_null_seq as bigint start with 1 ; +create sequence migtest_fk_set_null_seq as bigint start with 1; create table migtest_e_basic ( id integer not null, @@ -85,7 +85,7 @@ create table migtest_e_basic ( ); create unique nonclustered index uq_migtest_e_basic_indextest2 on migtest_e_basic(indextest2) where indextest2 is not null; create unique nonclustered index uq_migtest_e_basic_indextest6 on migtest_e_basic(indextest6) where indextest6 is not null; -create sequence migtest_e_basic_seq as bigint start with 1 ; +create sequence migtest_e_basic_seq as bigint start with 1; create table migtest_e_enum ( id integer not null, @@ -93,14 +93,14 @@ create table migtest_e_enum ( constraint ck_migtest_e_enum_test_status check ( test_status in ('N','A','I')), constraint pk_migtest_e_enum primary key (id) ); -create sequence migtest_e_enum_seq as bigint start with 1 ; +create sequence migtest_e_enum_seq as bigint start with 1; create table migtest_e_history ( id integer not null, test_string nvarchar(255), constraint pk_migtest_e_history primary key (id) ); -create sequence migtest_e_history_seq as bigint start with 1 ; +create sequence migtest_e_history_seq as bigint start with 1; create table migtest_e_history2 ( id integer not null, @@ -109,28 +109,28 @@ create table migtest_e_history2 ( obsolete_string2 nvarchar(255), constraint pk_migtest_e_history2 primary key (id) ); -create sequence migtest_e_history2_seq as bigint start with 1 ; +create sequence migtest_e_history2_seq as bigint start with 1; create table migtest_e_history3 ( id integer not null, test_string nvarchar(255), constraint pk_migtest_e_history3 primary key (id) ); -create sequence migtest_e_history3_seq as bigint start with 1 ; +create sequence migtest_e_history3_seq as bigint start with 1; create table migtest_e_history4 ( id integer not null, test_number integer, constraint pk_migtest_e_history4 primary key (id) ); -create sequence migtest_e_history4_seq as bigint start with 1 ; +create sequence migtest_e_history4_seq as bigint start with 1; create table migtest_e_history5 ( id integer not null, test_number integer, constraint pk_migtest_e_history5 primary key (id) ); -create sequence migtest_e_history5_seq as bigint start with 1 ; +create sequence migtest_e_history5_seq as bigint start with 1; create table migtest_e_history6 ( id integer not null, @@ -138,7 +138,7 @@ create table migtest_e_history6 ( test_number2 integer not null, constraint pk_migtest_e_history6 primary key (id) ); -create sequence migtest_e_history6_seq as bigint start with 1 ; +create sequence migtest_e_history6_seq as bigint start with 1; create table migtest_e_ref ( id integer not null, @@ -146,42 +146,42 @@ create table migtest_e_ref ( constraint pk_migtest_e_ref primary key (id) ); alter table migtest_e_ref add constraint uq_migtest_e_ref_name unique (name); -create sequence migtest_e_ref_seq as bigint start with 1 ; +create sequence migtest_e_ref_seq as bigint start with 1; create table migtest_e_softdelete ( id integer not null, test_string nvarchar(255), constraint pk_migtest_e_softdelete primary key (id) ); -create sequence migtest_e_softdelete_seq as bigint start with 1 ; +create sequence migtest_e_softdelete_seq as bigint start with 1; create table migtest_mtm_c ( id integer not null, name nvarchar(255), constraint pk_migtest_mtm_c primary key (id) ); -create sequence migtest_mtm_c_seq as bigint start with 1 ; +create sequence migtest_mtm_c_seq as bigint start with 1; create table migtest_mtm_m ( id numeric(19) not null, name nvarchar(255), constraint pk_migtest_mtm_m primary key (id) ); -create sequence migtest_mtm_m_seq as bigint start with 1 ; +create sequence migtest_mtm_m_seq as bigint start with 1; create table migtest_oto_child ( id integer not null, name nvarchar(255), constraint pk_migtest_oto_child primary key (id) ); -create sequence migtest_oto_child_seq as bigint start with 1 ; +create sequence migtest_oto_child_seq as bigint start with 1; create table migtest_oto_master ( id numeric(19) not null, name nvarchar(255), constraint pk_migtest_oto_master primary key (id) ); -create sequence migtest_oto_master_seq as bigint start with 1 ; +create sequence migtest_oto_master_seq as bigint start with 1; 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/src/test/resources/dbmigration/migrationtest/sqlserver17/1.1.sql b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.1.sql index d4dcc9c00..f8ba67fe0 100644 --- a/src/test/resources/dbmigration/migrationtest/sqlserver17/1.1.sql +++ b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.1.sql @@ -4,7 +4,7 @@ create table migtest_e_user ( id integer not null, constraint pk_migtest_e_user primary key (id) ); -create sequence migtest_e_user_seq as bigint start with 1 ; +create sequence migtest_e_user_seq as bigint start with 1; create table migtest_mtm_c_migtest_mtm_m ( migtest_mtm_c_id integer not null, diff --git a/src/test/resources/dbmigration/migrationtest/sqlserver17/1.3.sql b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.3.sql index ae274869c..645d0879d 100644 --- a/src/test/resources/dbmigration/migrationtest/sqlserver17/1.3.sql +++ b/src/test/resources/dbmigration/migrationtest/sqlserver17/1.3.sql @@ -6,7 +6,7 @@ create table migtest_e_ref ( constraint pk_migtest_e_ref primary key (id) ); alter table migtest_e_ref add constraint uq_migtest_e_ref_name unique (name); -create sequence migtest_e_ref_seq as bigint start with 1 ; +create sequence migtest_e_ref_seq as bigint start with 1; IF OBJECT_ID('fk_migtest_ckey_detail_parent', 'F') IS NOT NULL alter table migtest_ckey_detail drop constraint fk_migtest_ckey_detail_parent; IF OBJECT_ID('fk_migtest_fk_cascade_one_id', 'F') IS NOT NULL alter table migtest_fk_cascade drop constraint fk_migtest_fk_cascade_one_id; diff --git a/src/test/resources/ebean.properties b/src/test/resources/ebean.properties index 21941d391..c2660f986 100644 --- a/src/test/resources/ebean.properties +++ b/src/test/resources/ebean.properties @@ -22,7 +22,7 @@ ebean.ddl.generate=true ebean.ddl.run=true ebean.ddl.header=-- Generated by ebean ${version} at ${timestamp} ebean.packages=org.tests -datasource.default=h2 +datasource.default=sqlserver #datasource.h2.capturestacktrace=true ebean.dumpMetricsOnShutdown=true