Merge pull request #2515 from ebean-orm/feature/oracle-maxInBinding

Add maxInBinding - Oracle support for large delete by ids
This commit is contained in:
Rob Bygrave
2022-01-28 09:50:01 +13:00
committed by GitHub
5 changed files with 21 additions and 11 deletions
@@ -55,12 +55,12 @@ public class DatabasePlatform {
protected boolean supportsSavepointId = true;
protected boolean useMigrationStoredProcedures = false;
/**
* Can we use native java time API objects in
* {@link ResultSet#getObject(int, Class)} and
* {@link PreparedStatement#setObject(int, Object)}.
*
*
* Not all drivers (DB2 e.g.) will support this.
*/
protected boolean supportsNativeJavaTime = true;
@@ -214,6 +214,8 @@ public class DatabasePlatform {
*/
protected PersistBatch persistBatchOnCascade = PersistBatch.ALL;
protected int maxInBinding;
/**
* The maximum length of table names - used specifically when derived
* default table names for intersection tables.
@@ -370,6 +372,13 @@ public class DatabasePlatform {
return inlineSqlUpdateLimit;
}
/**
* Return the maximum number of bind values this database platform allows or zero for no limit.
*/
public int getMaxInBinding() {
return maxInBinding;
}
/**
* Return the maximum table name length.
* <p>
@@ -23,6 +23,7 @@ public class OraclePlatform extends DatabasePlatform {
super();
this.platform = Platform.ORACLE;
this.supportsDeleteTableAlias = true;
this.maxInBinding = 1000;
this.maxTableNameLength = 30;
this.maxConstraintNameLength = 30;
this.dbEncrypt = new OracleDbEncrypt();
@@ -27,6 +27,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
// SQL Server unless we are using sequences
this.dbEncrypt = new SqlServerDbEncrypt();
this.persistBatchOnCascade = PersistBatch.NONE;
this.maxInBinding = 2000;
this.idInExpandedForm = true;
this.selectCountWithAlias = true;
this.selectCountWithColumnAlias = true;
@@ -1,7 +1,6 @@
package io.ebeaninternal.server.persist;
import io.ebean.*;
import io.ebean.annotation.Platform;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollection.ModifyListenMode;
import io.ebean.bean.EntityBean;
@@ -42,15 +41,15 @@ public final class DefaultPersister implements Persister {
* Actually does the persisting work.
*/
private final PersistExecute persistExecute;
private final SpiEbeanServer server;
private final BeanDescriptorManager beanDescriptorManager;
private final int maxInBinding;
public DefaultPersister(SpiEbeanServer server, Binder binder, BeanDescriptorManager descMgr) {
this.server = server;
this.beanDescriptorManager = descMgr;
this.persistExecute = new DefaultPersistExecute(binder, server.config().getPersistBatchSize());
this.maxInBinding = server.databasePlatform().getMaxInBinding();
}
@Override
@@ -645,18 +644,18 @@ public final class DefaultPersister implements Persister {
DeleteMode deleteMode = (permanent || !descriptor.isSoftDelete()) ? DeleteMode.HARD : DeleteMode.SOFT;
return delete(descriptor, null, idList, transaction, deleteMode);
}
/**
* Delete by Id or a List of Id's.
*/
private int delete(BeanDescriptor<?> descriptor, Object id, List<Object> idList, Transaction transaction, DeleteMode deleteMode) {
int rows = 0;
if (server.databasePlatform().isPlatform(Platform.SQLSERVER)) {
if (maxInBinding > 0) {
// SqlServer has a 2100 parameter limit, so delete max 2000 ids at once
// this gives space up to 100 more query parameters.
while (idList != null && idList.size() > 2000) {
rows += deleteBatch(descriptor, id, idList.subList(0, 2000), transaction, deleteMode);
idList = idList.subList(2000, idList.size());
while (idList != null && idList.size() > maxInBinding) {
rows += deleteBatch(descriptor, id, idList.subList(0, maxInBinding), transaction, deleteMode);
idList = idList.subList(maxInBinding, idList.size());
}
}
rows += deleteBatch(descriptor, id, idList, transaction, deleteMode);
@@ -282,7 +282,7 @@ public class TestQueryFilterMany extends BaseTestCase {
List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(2);
assertThat(sql.size()).isGreaterThan(1);
assertSql(sql.get(0)).contains(" from o_customer t0 left join contact t1 on t1.customer_id = t0.id where t1.first_name is not null order by t0.id; --bind()");
platformAssertIn(sql.get(1), " from contact_note t0 where (t0.contact_id)");
assertSql(sql.get(1)).contains(" and lower(t0.title) like");