mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#1268 - SQL Server fix for "for update" plus Sequences support plus refactor of sequences
This commit is contained in:
@@ -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(";");
|
||||
|
||||
@@ -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(";");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private int sequenceInitialValue;
|
||||
|
||||
private int sequenceAllocationSize;
|
||||
private int sequenceAllocationSize = 50;
|
||||
|
||||
/**
|
||||
* Used with Identity columns but no getGeneratedKeys support.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
private final ArrayStack<String> 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user