[jOOQ/jOOQ#10692] Don't batch X .. RETURNING statements

This commit is contained in:
Lukas Eder 2020-09-28 11:52:20 +02:00
parent 2811d8e18b
commit fbfa2e82ee
3 changed files with 77 additions and 8 deletions

View File

@ -91,6 +91,7 @@ import static org.jooq.util.sqlite.SQLiteDSL.rowid;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@ -140,6 +141,7 @@ import org.jooq.exception.DataAccessException;
import org.jooq.impl.Tools.BooleanDataKey;
import org.jooq.impl.Tools.DataKey;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.jdbc.BatchedPreparedStatement;
import org.jooq.tools.jdbc.JDBCUtils;
/**
@ -952,7 +954,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
// SQLite can select _rowid_ after the insert
case SQLITE: {
listener.executeStart(ctx);
result = ctx.statement().executeUpdate();
result = executeImmediate(ctx.statement()).executeUpdate();
ctx.rows(result);
listener.executeEnd(ctx);
@ -979,7 +981,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
case CUBRID: {
listener.executeStart(ctx);
result = ctx.statement().executeUpdate();
result = executeImmediate(ctx.statement()).executeUpdate();
ctx.rows(result);
listener.executeEnd(ctx);
@ -1153,9 +1155,20 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
}
}
/**
* Make sure a {@link PreparedStatement}, which may be a
* {@link BatchedPreparedStatement}, is executed immediately, not batched.
*/
private final PreparedStatement executeImmediate(PreparedStatement s) throws SQLException {
if (s.isWrapperFor(BatchedPreparedStatement.class))
s.unwrap(BatchedPreparedStatement.class).setExecuteImmediate(true);
return s;
}
private final ResultSet executeReturningGeneratedKeys(ExecuteContext ctx, ExecuteListener listener) throws SQLException {
listener.executeStart(ctx);
int result = ctx.statement().executeUpdate();
int result = executeImmediate(ctx.statement()).executeUpdate();
ctx.rows(result);
listener.executeEnd(ctx);
@ -1166,7 +1179,7 @@ abstract class AbstractDMLQuery<R extends Record> extends AbstractRowCountQuery
ResultSet rs;
listener.executeStart(ctx);
int result = ctx.statement().executeUpdate();
int result = executeImmediate(ctx.statement()).executeUpdate();
ctx.rows(result);
listener.executeEnd(ctx);

View File

@ -93,6 +93,21 @@ public class BatchedConnection extends DefaultConnection {
this.batchSize = batchSize;
}
// -------------------------------------------------------------------------
// XXX: Wrappers
// -------------------------------------------------------------------------
@SuppressWarnings("unchecked")
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return BatchedConnection.class == iface ? (T) this : super.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return BatchedConnection.class == iface || super.isWrapperFor(iface);
}
// -------------------------------------------------------------------------
// XXX: Utilities
// -------------------------------------------------------------------------

View File

@ -57,6 +57,7 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement {
private static final JooqLogger log = JooqLogger.getLogger(BatchedPreparedStatement.class);
int batches;
boolean executeImmediate;
public BatchedPreparedStatement(BatchedConnection connection, PreparedStatement delegate) {
super(delegate, connection);
@ -66,10 +67,23 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement {
return (BatchedConnection) super.getConnection();
}
public boolean getExecuteImmediate() {
return this.executeImmediate;
}
public void setExecuteImmediate(boolean executeImmediate) {
this.executeImmediate = executeImmediate;
}
private void resetBatches() {
batches = 0;
}
private void logExecuteImmediate() throws SQLException {
if (log.isDebugEnabled())
log.debug("BatchedStatement", "Skipped batching statement: " + getBatchedConnection().lastSQL);
}
private void logBatch() throws SQLException {
if (log.isDebugEnabled())
log.debug("BatchedStatement", "Batched " + batches + " times: " + getBatchedConnection().lastSQL);
@ -82,20 +96,47 @@ public class BatchedPreparedStatement extends DefaultPreparedStatement {
resetBatches();
}
// -------------------------------------------------------------------------
// XXX: Wrappers
// -------------------------------------------------------------------------
@SuppressWarnings("unchecked")
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return BatchedPreparedStatement.class == iface ? (T) this : super.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return BatchedPreparedStatement.class == iface || super.isWrapperFor(iface);
}
// -------------------------------------------------------------------------
// XXX: Executing queries
// -------------------------------------------------------------------------
@Override
public int executeUpdate() throws SQLException {
addBatch();
return 0;
if (executeImmediate) {
logExecuteImmediate();
return super.executeUpdate();
}
else {
addBatch();
return 0;
}
}
@Override
public boolean execute() throws SQLException {
addBatch();
return false;
if (executeImmediate) {
logExecuteImmediate();
return super.execute();
}
else {
addBatch();
return false;
}
}
@Override