diff --git a/src/main/java/io/ebean/config/ServerConfig.java b/src/main/java/io/ebean/config/ServerConfig.java
index a3f9348c9..4b17b276f 100644
--- a/src/main/java/io/ebean/config/ServerConfig.java
+++ b/src/main/java/io/ebean/config/ServerConfig.java
@@ -12,6 +12,7 @@ import io.ebean.cache.ServerCachePlugin;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbEncrypt;
import io.ebean.config.dbplatform.DbType;
+import io.ebean.config.dbplatform.IdType;
import io.ebean.event.BeanFindController;
import io.ebean.event.BeanPersistController;
import io.ebean.event.BeanPersistListener;
@@ -181,6 +182,11 @@ public class ServerConfig {
*/
private DatabasePlatform databasePlatform;
+ /**
+ * The preferred IdType (to override the default Platform type).
+ */
+ private IdType idType;
+
/**
* For DB's using sequences this is the number of sequence values prefetched.
*/
@@ -1721,6 +1727,20 @@ public class ServerConfig {
this.databasePlatform = databasePlatform;
}
+ /**
+ * Return the preferred DB platform IdType.
+ */
+ public IdType getIdType() {
+ return idType;
+ }
+
+ /**
+ * Set the preferred DB platform IdType.
+ */
+ public void setIdType(IdType idType) {
+ this.idType = idType;
+ }
+
/**
* Return the EncryptKeyManager.
*/
@@ -2722,6 +2742,7 @@ public class ServerConfig {
throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
}
+ idType = p.getEnum(IdType.class, "idType", idType);
persistBatch = p.getEnum(PersistBatch.class, "persistBatch", persistBatch);
persistBatchOnCascade = p.getEnum(PersistBatch.class, "persistBatchOnCascade", persistBatchOnCascade);
diff --git a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java
index 3b6073c60..190e69d97 100644
--- a/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/DatabasePlatform.java
@@ -6,6 +6,8 @@ import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.Platform;
import io.ebean.config.CustomDbTypeMapping;
import io.ebean.config.DbTypeConfig;
+import io.ebean.config.ServerConfig;
+import io.ebeaninternal.util.JdbcClose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -98,6 +100,10 @@ public class DatabasePlatform {
*/
protected DbIdentity dbIdentity = new DbIdentity();
+ protected boolean sequenceBatchMode = true;
+
+ protected int sequenceBatchSize = 20;
+
/**
* The history support for this database platform.
*/
@@ -206,10 +212,19 @@ public class DatabasePlatform {
return exceptionTranslator.translate(message, e);
}
+ /**
+ * Configure the platform given the server configuration.
+ */
+ public void configure(ServerConfig config) {
+ this.sequenceBatchSize = config.getDatabaseSequenceBatchSize();
+ configureIdType(config.getIdType());
+ configure(config.getDbTypeConfig(), config.isAllQuotedIdentifiers());
+ }
+
/**
* Configure UUID Storage etc based on ServerConfig settings.
*/
- public void configure(DbTypeConfig config, boolean allQuotedIdentifiers) {
+ protected void configure(DbTypeConfig config, boolean allQuotedIdentifiers) {
this.allQuotedIdentifiers = allQuotedIdentifiers;
addGeoTypes(config.getGeometrySRID());
configureIdType(config.getIdType());
@@ -263,6 +278,20 @@ public class DatabasePlatform {
return platform.name().toLowerCase();
}
+ /**
+ * Return true if we are using Sequence batch mode rather than STEP.
+ */
+ public boolean isSequenceBatchMode() {
+ return sequenceBatchMode;
+ }
+
+ /**
+ * Set to false to not use sequence batch mode but instead STEP mode.
+ */
+ public void setSequenceBatchMode(boolean sequenceBatchMode) {
+ this.sequenceBatchMode = sequenceBatchMode;
+ }
+
/**
* Return true if this database platform supports native ILIKE expression.
*/
@@ -304,10 +333,10 @@ public class DatabasePlatform {
* @param be the BackgroundExecutor that can be used to load the sequence if
* desired
* @param ds the DataSource
+ * @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
* @param seqName the name of the sequence
- * @param batchSize the number of sequences that should be loaded
*/
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
return null;
}
@@ -586,6 +615,14 @@ public class DatabasePlatform {
return sql;
}
+ /**
+ * For update hint on the FROM clause (SQL server only).
+ */
+ public String fromForUpdate(Query.ForUpdate forUpdateMode) {
+ // return null except for sql server
+ return null;
+ }
+
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
// silently assume the database does not support the "for update" clause.
logger.info("it seems your database does not support the 'for update' clause");
@@ -618,18 +655,7 @@ public class DatabasePlatform {
try {
return tables.next();
} finally {
- close(tables);
- }
- }
-
- /**
- * Close the resultSet.
- */
- protected void close(ResultSet resultSet) {
- try {
- resultSet.close();
- } catch (SQLException e) {
- logger.error("Error closing resultSet", e);
+ JdbcClose.close(tables);
}
}
diff --git a/src/main/java/io/ebean/config/dbplatform/SequenceBatchIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/SequenceBatchIdGenerator.java
new file mode 100644
index 000000000..6444e0d55
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/SequenceBatchIdGenerator.java
@@ -0,0 +1,56 @@
+package io.ebean.config.dbplatform;
+
+import io.ebean.BackgroundExecutor;
+
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Database sequence based IdGenerator using Sequence Step 1 but batch fetch many sequence values.
+ */
+public abstract class SequenceBatchIdGenerator extends SequenceIdGenerator {
+
+ /**
+ * Construct where batchSize is the sequence step size.
+ *
+ */
+ public SequenceBatchIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
+ super(be, ds, seqName, batchSize);
+ }
+
+ /**
+ * If allocateSize is large load some sequences in a background thread.
+ *
+ * For example, when inserting a bean with a cascade on a OneToMany with many
+ * beans Ebean can call this to ensure .
+ *
+ */
+ @Override
+ public void preAllocateIds(int requestSize) {
+ if (allocationSize > 1 && requestSize > allocationSize) {
+ // only bother if allocateSize is bigger than
+ // the normal loading batchSize
+ if (requestSize > 100) {
+ // max out at 100 for now
+ requestSize = 100;
+ }
+ loadInBackground(requestSize);
+ }
+ }
+
+ /**
+ * Add the next set of Ids as the next value plus all the following numbers up to the step size.
+ */
+ protected List readIds(ResultSet resultSet, int loadSize) throws SQLException {
+
+ List newIds = new ArrayList<>(loadSize);
+ while (resultSet.next()) {
+ newIds.add(resultSet.getLong(1));
+ }
+ return newIds;
+ }
+
+}
diff --git a/src/main/java/io/ebean/config/dbplatform/SequenceIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/SequenceIdGenerator.java
index 3d6da7357..985a545c6 100644
--- a/src/main/java/io/ebean/config/dbplatform/SequenceIdGenerator.java
+++ b/src/main/java/io/ebean/config/dbplatform/SequenceIdGenerator.java
@@ -2,6 +2,7 @@ package io.ebean.config.dbplatform;
import io.ebean.BackgroundExecutor;
import io.ebean.Transaction;
+import io.ebeaninternal.util.JdbcClose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -12,13 +13,15 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* Database sequence based IdGenerator.
*/
public abstract class SequenceIdGenerator implements PlatformIdGenerator {
- private static final Logger logger = LoggerFactory.getLogger(SequenceIdGenerator.class);
+ protected static final Logger logger = LoggerFactory.getLogger("io.ebean.SEQ");
/**
* Used to synchronise the idList access.
@@ -41,18 +44,18 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
protected final ArrayList idList = new ArrayList<>(50);
- protected final int batchSize;
+ protected final int allocationSize;
- protected int currentlyBackgroundLoading;
+ protected boolean currentlyBackgroundLoading;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
- public SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
+ protected SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int allocationSize) {
this.backgroundExecutor = be;
this.dataSource = ds;
this.seqName = seqName;
- this.batchSize = batchSize;
+ this.allocationSize = allocationSize;
}
public abstract String getSql(int batchSize);
@@ -81,26 +84,8 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
*
*/
@Override
- public void preAllocateIds(int allocateSize) {
- if (batchSize > 1 && allocateSize > batchSize) {
- // only bother if allocateSize is bigger than
- // the normal loading batchSize
- if (allocateSize > 100) {
- // max out at 100 for now
- allocateSize = 100;
- }
- loadLargeAllocation(allocateSize);
- }
- }
-
- /**
- * Called by preAllocateIds when we know that a large number of Id's is going
- * to be needed shortly.
- */
- protected void loadLargeAllocation(final int allocateSize) {
- // preAllocateIds was called with a relatively large batchSize
- // so we will just go ahead and load those anyway in background
- backgroundExecutor.execute(() -> loadMoreIds(allocateSize, null));
+ public void preAllocateIds(int requestSize) {
+ // do nothing by default
}
/**
@@ -113,80 +98,80 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
public Object nextId(Transaction t) {
synchronized (monitor) {
- if (idList.isEmpty()) {
- loadMoreIds(batchSize, t);
- }
- Long nextId = idList.remove(0);
-
- if (batchSize > 1) {
- if (idList.size() <= batchSize / 2) {
- loadBatchInBackground();
- }
+ int size = idList.size();
+ if (size > 0) {
+ maybeLoadMoreInBackground(size);
+ } else {
+ loadMore(allocationSize);
}
- return nextId;
+ return idList.remove(0);
}
}
- /**
- * Load another batch of Id's using a background thread.
- */
- protected void loadBatchInBackground() {
-
- // single threaded processing...
- synchronized (backgroundLoadMonitor) {
-
- if (currentlyBackgroundLoading > 0) {
- // skip as already background loading
- logger.debug("... skip background sequence load (another load in progress)");
- return;
+ private void maybeLoadMoreInBackground(int currentSize) {
+ if (allocationSize > 1) {
+ if (currentSize <= allocationSize / 2) {
+ loadInBackground(allocationSize);
}
-
- currentlyBackgroundLoading = batchSize;
-
- backgroundExecutor.execute(() -> {
- loadMoreIds(batchSize, null);
- synchronized (backgroundLoadMonitor) {
- currentlyBackgroundLoading = 0;
- }
- });
}
}
- protected void loadMoreIds(final int numberToLoad, Transaction t) {
-
- ArrayList newIds = getMoreIds(numberToLoad, t);
-
- if (logger.isDebugEnabled()) {
- logger.debug("... seq:" + seqName + " loaded:" + numberToLoad + " ids:" + newIds);
- }
-
+ private void loadMore(int requestSize) {
+ List newIds = getMoreIds(requestSize);
synchronized (monitor) {
idList.addAll(newIds);
}
}
+ /**
+ * Load another batch of Id's using a background thread.
+ */
+ protected void loadInBackground(final int requestSize) {
+
+ // single threaded processing...
+ synchronized (backgroundLoadMonitor) {
+ if (currentlyBackgroundLoading) {
+ // skip as already background loading
+ logger.debug("... skip background sequence load (another load in progress)");
+ return;
+ }
+
+ currentlyBackgroundLoading = true;
+
+ backgroundExecutor.execute(() -> {
+ loadMore(requestSize);
+ synchronized (backgroundLoadMonitor) {
+ currentlyBackgroundLoading = false;
+ }
+ });
+ }
+ }
+
+ /**
+ * Read the resultSet returning the list of Id values.
+ */
+ protected abstract List readIds(ResultSet resultSet, int loadSize) throws SQLException;
+
/**
* Get more Id's by executing a query and reading the Id's returned.
*/
- protected ArrayList getMoreIds(int loadSize, Transaction t) {
+ protected List getMoreIds(int requestSize) {
- String sql = getSql(loadSize);
+ String sql = getSql(requestSize);
- ArrayList newIds = new ArrayList<>(loadSize);
-
- boolean useTxnConnection = t != null;
-
- Connection c = null;
- PreparedStatement pstmt = null;
- ResultSet rset = null;
+ Connection connection = null;
+ PreparedStatement statement = null;
+ ResultSet resultSet = null;
try {
- c = useTxnConnection ? t.getConnection() : dataSource.getConnection();
+ connection = dataSource.getConnection();
- pstmt = c.prepareStatement(sql);
- rset = pstmt.executeQuery();
- while (rset.next()) {
- newIds.add(rset.getLong(1));
+ statement = connection.prepareStatement(sql);
+ resultSet = statement.executeQuery();
+
+ List newIds = readIds(resultSet, requestSize);
+ if (logger.isTraceEnabled()) {
+ logger.trace("seq:{} loaded:{} sql:{}", seqName, newIds.size(), sql);
}
if (newIds.isEmpty()) {
throw new PersistenceException("Always expecting more than 1 row from " + sql);
@@ -197,46 +182,24 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
} catch (SQLException e) {
if (e.getMessage().contains("Database is already closed")) {
String msg = "Error getting SEQ when DB shutting down " + e.getMessage();
- logger.info(msg);
+ logger.error(msg);
System.out.println(msg);
- return newIds;
+ return Collections.emptyList();
} else {
throw new PersistenceException("Error getting sequence nextval", e);
}
} finally {
- if (useTxnConnection) {
- closeResources(null, pstmt, rset);
- } else {
- closeResources(c, pstmt, rset);
- }
+ closeResources(connection, statement, resultSet);
}
}
/**
* Close the JDBC resources.
*/
- protected void closeResources(Connection c, PreparedStatement pstmt, ResultSet rset) {
- try {
- if (rset != null) {
- rset.close();
- }
- } catch (SQLException e) {
- logger.error("Error closing ResultSet", e);
- }
- try {
- if (pstmt != null) {
- pstmt.close();
- }
- } catch (SQLException e) {
- logger.error("Error closing PreparedStatement", e);
- }
- try {
- if (c != null) {
- c.close();
- }
- } catch (SQLException e) {
- logger.error("Error closing Connection", e);
- }
+ private void closeResources(Connection connection, PreparedStatement statement, ResultSet resultSet) {
+ JdbcClose.close(resultSet);
+ JdbcClose.close(statement);
+ JdbcClose.close(connection);
}
}
diff --git a/src/main/java/io/ebean/config/dbplatform/SequenceStepIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/SequenceStepIdGenerator.java
new file mode 100644
index 000000000..3e632e5fa
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/SequenceStepIdGenerator.java
@@ -0,0 +1,38 @@
+package io.ebean.config.dbplatform;
+
+import io.ebean.BackgroundExecutor;
+
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Database sequence based IdGenerator using Sequence Step (e.g. step 50).
+ */
+public abstract class SequenceStepIdGenerator extends SequenceIdGenerator {
+
+ /**
+ * Construct with stepSize (typically 50).
+ */
+ protected SequenceStepIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
+ super(be, ds, seqName, stepSize);
+ }
+
+ /**
+ * Add the next set of Ids as the next value plus all the following numbers up to the step size.
+ */
+ protected List readIds(ResultSet resultSet, int ignoreRequestSize) throws SQLException {
+
+ List newIds = new ArrayList<>(allocationSize);
+ if (resultSet.next()) {
+ long start = resultSet.getLong(1);
+ for (int i = 0; i < allocationSize; i++) {
+ newIds.add(start + i);
+ }
+ }
+ return newIds;
+ }
+
+}
diff --git a/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java b/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java
index c8bcbd7f6..793afee2d 100644
--- a/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java
+++ b/src/main/java/io/ebean/config/dbplatform/db2/DB2Platform.java
@@ -55,10 +55,9 @@ public class DB2Platform extends DatabasePlatform {
* sequence values.
*/
@Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be,
- DataSource ds, String seqName, int batchSize) {
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
- return new DB2SequenceIdGenerator(be, ds, seqName, batchSize);
+ return new DB2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
}
diff --git a/src/main/java/io/ebean/config/dbplatform/db2/DB2SequenceIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/db2/DB2SequenceIdGenerator.java
index 788e4e396..a5170a759 100644
--- a/src/main/java/io/ebean/config/dbplatform/db2/DB2SequenceIdGenerator.java
+++ b/src/main/java/io/ebean/config/dbplatform/db2/DB2SequenceIdGenerator.java
@@ -1,14 +1,14 @@
package io.ebean.config.dbplatform.db2;
import io.ebean.BackgroundExecutor;
-import io.ebean.config.dbplatform.SequenceIdGenerator;
+import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* DB2 specific sequence Id Generator.
*/
-public class DB2SequenceIdGenerator extends SequenceIdGenerator {
+public class DB2SequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
private final String unionBaseSql;
diff --git a/src/main/java/io/ebean/config/dbplatform/h2/H2Platform.java b/src/main/java/io/ebean/config/dbplatform/h2/H2Platform.java
index 7c3c78a36..1b093d880 100644
--- a/src/main/java/io/ebean/config/dbplatform/h2/H2Platform.java
+++ b/src/main/java/io/ebean/config/dbplatform/h2/H2Platform.java
@@ -46,10 +46,8 @@ public class H2Platform extends DatabasePlatform {
* sequence values.
*/
@Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
- String seqName, int batchSize) {
-
- return new H2SequenceIdGenerator(be, ds, seqName, batchSize);
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
+ return new H2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
@Override
diff --git a/src/main/java/io/ebean/config/dbplatform/h2/H2SequenceIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/h2/H2SequenceIdGenerator.java
index 4dafed231..b4e875511 100644
--- a/src/main/java/io/ebean/config/dbplatform/h2/H2SequenceIdGenerator.java
+++ b/src/main/java/io/ebean/config/dbplatform/h2/H2SequenceIdGenerator.java
@@ -1,14 +1,14 @@
package io.ebean.config.dbplatform.h2;
import io.ebean.BackgroundExecutor;
-import io.ebean.config.dbplatform.SequenceIdGenerator;
+import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* H2 specific sequence Id Generator.
*/
-public class H2SequenceIdGenerator extends SequenceIdGenerator {
+public class H2SequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
private final String unionBaseSql;
diff --git a/src/main/java/io/ebean/config/dbplatform/hsqldb/HsqldbPlatform.java b/src/main/java/io/ebean/config/dbplatform/hsqldb/HsqldbPlatform.java
index 80a3a032e..1450b01f7 100644
--- a/src/main/java/io/ebean/config/dbplatform/hsqldb/HsqldbPlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/hsqldb/HsqldbPlatform.java
@@ -31,9 +31,8 @@ public class HsqldbPlatform extends DatabasePlatform {
}
@Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
-
- return new H2SequenceIdGenerator(be, ds, seqName, batchSize);
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
+ return new H2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
}
diff --git a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java
index f004be7d5..f9973c243 100644
--- a/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/mysql/MySqlPlatform.java
@@ -1,16 +1,13 @@
package io.ebean.config.dbplatform.mysql;
-import io.ebean.BackgroundExecutor;
import io.ebean.Query;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
-import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.config.dbplatform.SqlErrorCodes;
-import javax.sql.DataSource;
import java.sql.Types;
/**
@@ -64,16 +61,6 @@ public class MySqlPlatform extends DatabasePlatform {
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
}
- /**
- * Return null in case there is a sequence annotation.
- */
- @Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be,
- DataSource ds, String seqName, int batchSize) {
-
- return null;
- }
-
@Override
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
// NOWAIT and SKIP LOCKED currently not supported with MySQL
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
index 5f0b1ca3e..636390dfc 100644
--- a/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/OraclePlatform.java
@@ -70,9 +70,8 @@ public class OraclePlatform extends DatabasePlatform {
}
@Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
-
- return new OracleSequenceIdGenerator(be, ds, seqName, batchSize);
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
+ return new OracleSequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
@Override
diff --git a/src/main/java/io/ebean/config/dbplatform/oracle/OracleSequenceIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/oracle/OracleSequenceIdGenerator.java
index b0a7a2f70..32dd7a28e 100644
--- a/src/main/java/io/ebean/config/dbplatform/oracle/OracleSequenceIdGenerator.java
+++ b/src/main/java/io/ebean/config/dbplatform/oracle/OracleSequenceIdGenerator.java
@@ -1,14 +1,14 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.BackgroundExecutor;
-import io.ebean.config.dbplatform.SequenceIdGenerator;
+import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* Oracle specific sequence Id Generator.
*/
-public class OracleSequenceIdGenerator extends SequenceIdGenerator {
+public class OracleSequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
diff --git a/src/main/java/io/ebean/config/dbplatform/postgres/PostgresPlatform.java b/src/main/java/io/ebean/config/dbplatform/postgres/PostgresPlatform.java
index 04d1b0384..20d9107d1 100644
--- a/src/main/java/io/ebean/config/dbplatform/postgres/PostgresPlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/postgres/PostgresPlatform.java
@@ -90,9 +90,9 @@ public class PostgresPlatform extends DatabasePlatform {
* Create a Postgres specific sequence IdGenerator.
*/
@Override
- public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
- return new PostgresSequenceIdGenerator(be, ds, seqName, batchSize);
+ return new PostgresSequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
@Override
diff --git a/src/main/java/io/ebean/config/dbplatform/postgres/PostgresSequenceIdGenerator.java b/src/main/java/io/ebean/config/dbplatform/postgres/PostgresSequenceIdGenerator.java
index d01a70db5..4550c926d 100644
--- a/src/main/java/io/ebean/config/dbplatform/postgres/PostgresSequenceIdGenerator.java
+++ b/src/main/java/io/ebean/config/dbplatform/postgres/PostgresSequenceIdGenerator.java
@@ -1,14 +1,14 @@
package io.ebean.config.dbplatform.postgres;
import io.ebean.BackgroundExecutor;
-import io.ebean.config.dbplatform.SequenceIdGenerator;
+import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* Postgres specific sequence Id Generator.
*/
-public class PostgresSequenceIdGenerator extends SequenceIdGenerator {
+public class PostgresSequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
diff --git a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasicSqlLimiter.java b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasicSqlLimiter.java
index 64494f34d..3ac56f727 100644
--- a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasicSqlLimiter.java
+++ b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerBasicSqlLimiter.java
@@ -13,7 +13,7 @@ public class SqlServerBasicSqlLimiter implements BasicSqlLimiter {
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append(dbSql);
if (!dbSql.toLowerCase().contains("order by")) {
- sb.append(" order by 1 ");
+ sb.append(" order by 1");
}
sb.append(" ").append("offset");
sb.append(" ").append(firstRow).append(" rows");
diff --git a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java
index f0ed6744a..102a7e0d5 100644
--- a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java
+++ b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerPlatform.java
@@ -1,13 +1,18 @@
package io.ebean.config.dbplatform.sqlserver;
+import io.ebean.BackgroundExecutor;
+import io.ebean.Query;
import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.Platform;
+import io.ebean.config.ServerConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
+import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.config.dbplatform.SqlErrorCodes;
+import javax.sql.DataSource;
import java.sql.Types;
/**
@@ -18,8 +23,8 @@ public class SqlServerPlatform extends DatabasePlatform {
public SqlServerPlatform() {
super();
this.platform = Platform.SQLSERVER;
- // effectively disable persistBatchOnCascade mode for SQL Server
- // due to lack of support for getGeneratedKeys in batch mode
+ // disable persistBatchOnCascade mode for
+ // SQL Server unless we are using sequences
this.persistBatchOnCascade = PersistBatch.NONE;
this.idInExpandedForm = true;
this.selectCountWithAlias = true;
@@ -29,12 +34,14 @@ public class SqlServerPlatform extends DatabasePlatform {
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
+ this.dbIdentity.setSupportsSequence(true);
+ this.sequenceBatchMode = false;
this.exceptionTranslator =
new SqlErrorCodes()
.addAcquireLock("1222")
.addDuplicateKey("2601", "2627")
- .addDataIntegrity("544", "8114", "8115")
+ .addDataIntegrity("544", "547", "8114", "8115")
.build();
this.openQuote = "[";
@@ -67,8 +74,45 @@ public class SqlServerPlatform extends DatabasePlatform {
}
+ @Override
+ public void configure(ServerConfig config) {
+ super.configure(config);
+ if (dbIdentity.getIdType() == IdType.SEQUENCE) {
+ this.persistBatchOnCascade = PersistBatch.ALL;
+ }
+ }
+
@Override
protected void escapeLikeCharacter(char ch, StringBuilder sb) {
sb.append('[').append(ch).append(']');
}
+
+ /**
+ * Create a Postgres specific sequence IdGenerator.
+ */
+ @Override
+ public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
+ return new SqlServerStepSequence(be, ds, seqName, stepSize);
+ }
+
+ /**
+ * For update is part of the FROM clause on the base table for sql server.
+ */
+ @Override
+ public String fromForUpdate(Query.ForUpdate forUpdateMode) {
+ switch (forUpdateMode) {
+ case SKIPLOCKED:
+ return "with (updlock,readpast)";
+ case NOWAIT:
+ return "with (updlock,nowait)";
+ default:
+ return "with (updlock)";
+ }
+ }
+
+ @Override
+ protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
+ // for update are hints on from clause of base table
+ return sql;
+ }
}
diff --git a/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequence.java b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequence.java
new file mode 100644
index 000000000..d9a53a9f7
--- /dev/null
+++ b/src/main/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequence.java
@@ -0,0 +1,24 @@
+package io.ebean.config.dbplatform.sqlserver;
+
+import io.ebean.BackgroundExecutor;
+import io.ebean.config.dbplatform.SequenceStepIdGenerator;
+
+import javax.sql.DataSource;
+
+public class SqlServerStepSequence extends SequenceStepIdGenerator {
+
+ private final String nextSql;
+
+ /**
+ * Construct where batchSize is the sequence step size.
+ */
+ public SqlServerStepSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
+ super(be, ds, seqName, stepSize);
+ this.nextSql = "select next value for "+seqName;
+ }
+
+ @Override
+ public String getSql(int batchSize) {
+ return nextSql;
+ }
+}
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 55057bddf..66e5e64e0 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/PlatformDdl.java
@@ -308,9 +308,7 @@ public class PlatformDdl {
if (initialValue > 1) {
sb.append(" start with ").append(initialValue);
}
- if (allocationSize > 0 && allocationSize != 50) {
- // at this stage ignoring allocationSize 50 as this is the 'default' and
- // not consistent with the way Ebean batch fetches sequence values
+ if (allocationSize > 1) {
sb.append(" increment by ").append(allocationSize);
}
sb.append(";");
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 16b541d88..843abad99 100644
--- a/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java
+++ b/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java
@@ -121,9 +121,7 @@ public class SqlServerDdl extends PlatformDdl {
} else {
sb.append(" start with 1 ");
}
- if (allocationSize > 0 && allocationSize != 50) {
- // at this stage ignoring allocationSize 50 as this is the 'default' and
- // not consistent with the way Ebean batch fetches sequence values
+ if (allocationSize > 1) {
sb.append(" increment by ").append(allocationSize);
}
sb.append(";");
diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java b/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
index ff4fd4338..0f72ca48c 100644
--- a/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
+++ b/src/main/java/io/ebeaninternal/server/core/DefaultContainer.java
@@ -270,7 +270,7 @@ public class DefaultContainer implements SpiContainer {
config.setDatabasePlatform(platform);
}
logger.info("DatabasePlatform name:{} platform:{}", config.getName(), platform.getName());
- platform.configure(config.getDbTypeConfig(), config.isAllQuotedIdentifiers());
+ platform.configure(config);
}
/**
diff --git a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java
index ed2945ef6..618183220 100644
--- a/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java
+++ b/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptorManager.java
@@ -173,8 +173,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private final BackgroundExecutor backgroundExecutor;
- private final int dbSequenceBatchSize;
-
private final EncryptKeyManager encryptKeyManager;
private final IdBinderFactory idBinderFactory;
@@ -206,7 +204,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
this.serverName = InternString.intern(serverConfig.getName());
this.cacheManager = config.getCacheManager();
this.docStoreFactory = config.getDocStoreFactory();
- this.dbSequenceBatchSize = serverConfig.getDatabaseSequenceBatchSize();
this.backgroundExecutor = config.getBackgroundExecutor();
this.dataSource = serverConfig.getDataSource();
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
@@ -1391,12 +1388,16 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
seqName = namingConvention.getSequenceName(desc.getBaseTable(), primaryKeyColumn);
}
- // create the sequence based IdGenerator
- desc.setIdGenerator(createSequenceIdGenerator(seqName));
+ if (databasePlatform.isSequenceBatchMode()) {
+ // use sequence next step 1 as we are going to batch fetch them instead
+ desc.setSequenceAllocationSize(1);
+ }
+ int stepSize = desc.getSequenceAllocationSize();
+ desc.setIdGenerator(createSequenceIdGenerator(seqName, stepSize));
}
- private PlatformIdGenerator createSequenceIdGenerator(String seqName) {
- return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSource, seqName, dbSequenceBatchSize);
+ private PlatformIdGenerator createSequenceIdGenerator(String seqName, int stepSize) {
+ return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSource, stepSize, seqName);
}
private void createByteCode(DeployBeanDescriptor> deploy) {
diff --git a/src/main/java/io/ebeaninternal/server/deploy/DbSqlContext.java b/src/main/java/io/ebeaninternal/server/deploy/DbSqlContext.java
index fa1563866..ff5402dbc 100644
--- a/src/main/java/io/ebeaninternal/server/deploy/DbSqlContext.java
+++ b/src/main/java/io/ebeaninternal/server/deploy/DbSqlContext.java
@@ -129,4 +129,9 @@ public interface DbSqlContext {
* Start group by clause.
*/
void startGroupBy();
+
+ /**
+ * Append 'for update' lock hints on FROM clause (sql server only).
+ */
+ void appendFromForUpdate();
}
diff --git a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
index 36e14a2e8..83416486a 100644
--- a/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
+++ b/src/main/java/io/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
@@ -107,7 +107,7 @@ public class DeployBeanDescriptor {
private int sequenceInitialValue;
- private int sequenceAllocationSize;
+ private int sequenceAllocationSize = 50;
/**
* Used with Identity columns but no getGeneratedKeys support.
diff --git a/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java b/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java
index 6ae7a12a0..c178371ee 100644
--- a/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java
+++ b/src/main/java/io/ebeaninternal/server/query/CQueryBuilder.java
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
+import io.ebean.Query;
import io.ebean.RawSql;
import io.ebean.RawSqlBuilder;
import io.ebean.annotation.Platform;
@@ -671,4 +672,16 @@ class CQueryBuilder {
boolean isPlatformDistinctOn() {
return dbPlatform.isPlatform(Platform.POSTGRES);
}
+
+ /**
+ * Return the 'for update' FROM hint (sql server).
+ */
+ public String fromForUpdate(SpiQuery> query) {
+ Query.ForUpdate mode = query.getForUpdateMode();
+ if (mode == null) {
+ return null;
+ } else {
+ return dbPlatform.fromForUpdate(mode);
+ }
+ }
}
diff --git a/src/main/java/io/ebeaninternal/server/query/DefaultDbSqlContext.java b/src/main/java/io/ebeaninternal/server/query/DefaultDbSqlContext.java
index cae5da9f0..a2138104b 100644
--- a/src/main/java/io/ebeaninternal/server/query/DefaultDbSqlContext.java
+++ b/src/main/java/io/ebeaninternal/server/query/DefaultDbSqlContext.java
@@ -26,6 +26,8 @@ class DefaultDbSqlContext implements DbSqlContext {
private final ArrayStack prefixStack = new ArrayStack<>();
+ private final String fromForUpdate;
+
private boolean useColumnAlias;
private int columnIndex;
@@ -55,7 +57,8 @@ class DefaultDbSqlContext implements DbSqlContext {
* Construct for SELECT clause (with column alias settings).
*/
DefaultDbSqlContext(SqlTreeAlias alias, CQueryBuilder builder,
- boolean alwaysUseColumnAlias, CQueryHistorySupport historySupport, CQueryDraftSupport draftSupport) {
+ boolean alwaysUseColumnAlias, CQueryHistorySupport historySupport,
+ CQueryDraftSupport draftSupport, String fromForUpdate) {
this.alias = alias;
this.tableAliasPlaceHolder = builder.tableAliasPlaceHolder;
@@ -64,6 +67,14 @@ class DefaultDbSqlContext implements DbSqlContext {
this.draftSupport = draftSupport;
this.historySupport = historySupport;
this.historyQuery = (historySupport != null);
+ this.fromForUpdate = fromForUpdate;
+ }
+
+ @Override
+ public void appendFromForUpdate() {
+ if (fromForUpdate != null) {
+ append(" ").append(fromForUpdate);
+ }
}
@Override
diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java
index d5e0f408c..d5ea84855 100644
--- a/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java
+++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeBuilder.java
@@ -119,9 +119,10 @@ public final class SqlTreeBuilder {
this.alias = new SqlTreeAlias(request.getBaseTableAlias());
this.distinctOnPlatform = builder.isPlatformDistinctOn();
+ String fromForUpdate = builder.fromForUpdate(query);
CQueryHistorySupport historySupport = builder.getHistorySupport(query);
CQueryDraftSupport draftSupport = builder.getDraftSupport(query);
- this.ctx = new DefaultDbSqlContext(alias, builder, !subQuery, historySupport, draftSupport);
+ this.ctx = new DefaultDbSqlContext(alias, builder, !subQuery, historySupport, draftSupport, fromForUpdate);
}
/**
diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
index b956115b6..bb93b25e1 100644
--- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
+++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
@@ -68,6 +68,7 @@ final class SqlTreeNodeRoot extends SqlTreeNodeBean {
ctx.append(desc.getBaseTable(temporalMode));
ctx.append(" ").append(baseTableAlias);
+ ctx.appendFromForUpdate();
if (includeJoin != null) {
String a1 = baseTableAlias;
diff --git a/src/main/java/io/ebeaninternal/util/JdbcClose.java b/src/main/java/io/ebeaninternal/util/JdbcClose.java
index 647f34709..f74e3dd46 100644
--- a/src/main/java/io/ebeaninternal/util/JdbcClose.java
+++ b/src/main/java/io/ebeaninternal/util/JdbcClose.java
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
/**
* Utility for closing raw Jdbc resources.
@@ -14,6 +15,19 @@ public class JdbcClose {
private static final Logger logger = LoggerFactory.getLogger(JdbcClose.class);
+ /**
+ * Close the resultSet logging if an error occurs.
+ */
+ public static void close(Statement statement) {
+ try {
+ if (statement != null) {
+ statement.close();
+ }
+ } catch (SQLException e) {
+ logger.warn("Error closing statement", e);
+ }
+ }
+
/**
* Close the resultSet logging if an error occurs.
*/
diff --git a/src/test/java/io/ebean/config/MatchingNamingConventionTest.java b/src/test/java/io/ebean/config/MatchingNamingConventionTest.java
index 8f29e2357..2cca6c06d 100644
--- a/src/test/java/io/ebean/config/MatchingNamingConventionTest.java
+++ b/src/test/java/io/ebean/config/MatchingNamingConventionTest.java
@@ -16,10 +16,13 @@ public class MatchingNamingConventionTest {
}
@Test
- public void getColumnFromProperty_when_allQuoted() throws Exception {
+ public void getColumnFromProperty_when_allQuoted() {
SqlServerPlatform platform = new SqlServerPlatform();
- platform.configure(new DbTypeConfig(), true);
+
+ ServerConfig config = new ServerConfig();
+ config.setAllQuotedIdentifiers(true);
+ platform.configure(config);
NamingConvention nc = new MatchingNamingConvention();
nc.setDatabasePlatform(platform);
@@ -29,7 +32,7 @@ public class MatchingNamingConventionTest {
}
@Test
- public void getColumnFromProperty() throws Exception {
+ public void getColumnFromProperty() {
String fkCol = "bridgetab_userId";
String col = namingConvention.getColumnFromProperty(null, fkCol);
diff --git a/src/test/java/io/ebean/config/ServerConfigTest.java b/src/test/java/io/ebean/config/ServerConfigTest.java
index 860ad9582..0eea08122 100644
--- a/src/test/java/io/ebean/config/ServerConfigTest.java
+++ b/src/test/java/io/ebean/config/ServerConfigTest.java
@@ -1,6 +1,7 @@
package io.ebean.config;
import io.ebean.annotation.PersistBatch;
+import io.ebean.config.dbplatform.IdType;
import org.avaje.datasource.DataSourceConfig;
import org.junit.Test;
@@ -46,6 +47,7 @@ public class ServerConfigTest {
props.setProperty("autoReadOnlyDataSource", "true");
props.setProperty("disableL2Cache", "true");
props.setProperty("notifyL2CacheInForeground", "true");
+ props.setProperty("idType", "SEQUENCE");
serverConfig.loadFromProperties(props);
@@ -54,6 +56,7 @@ public class ServerConfigTest {
assertTrue(serverConfig.isDbOffline());
assertTrue(serverConfig.isAutoReadOnlyDataSource());
+ assertEquals(IdType.SEQUENCE, serverConfig.getIdType());
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatch());
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatchOnCascade());
assertEquals(ServerConfig.DbUuid.BINARY, serverConfig.getDbTypeConfig().getDbUuid());
diff --git a/src/test/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequenceTest.java b/src/test/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequenceTest.java
new file mode 100644
index 000000000..3745ef4fa
--- /dev/null
+++ b/src/test/java/io/ebean/config/dbplatform/sqlserver/SqlServerStepSequenceTest.java
@@ -0,0 +1,55 @@
+package io.ebean.config.dbplatform.sqlserver;
+
+import io.ebean.BackgroundExecutor;
+import io.ebean.BaseTestCase;
+import io.ebean.annotation.ForPlatform;
+import io.ebean.annotation.Platform;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.sql.DataSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SqlServerStepSequenceTest extends BaseTestCase {
+
+ private static final Logger log = LoggerFactory.getLogger(SqlServerStepSequenceTest.class);
+
+ @Ignore
+ @ForPlatform(Platform.SQLSERVER)
+ @Test
+ public void seq() {
+
+
+ server().createSqlUpdate("drop sequence if exists sqls_testseq_9876").execute();
+ server().createSqlUpdate("create sequence sqls_testseq_9876 start with 1 increment by 50").execute();
+
+ BackgroundExecutor be = server().getBackgroundExecutor();
+ DataSource ds = server().getPluginApi().getDataSource();
+
+ SqlServerStepSequence s = new SqlServerStepSequence(be, ds, "sqls_testseq_9876", 50);
+
+ Object id = s.nextId(null);
+ assertThat(id).isEqualTo(1L);
+
+ for (int i = 0; i < 20; i++) {
+ Object val = s.nextId(null);
+ log.warn("val: "+val);
+ }
+
+ log.warn("here");
+
+ for (int i = 0; i < 20; i++) {
+ Object val = s.nextId(null);
+ log.warn("val: "+val);
+ }
+
+ for (int i = 0; i < 100; i++) {
+ Object val = s.nextId(null);
+ log.warn("val: "+val);
+ }
+ }
+
+}