diff --git a/jOOQ/src/main/java/org/jooq/ExecuteContext.java b/jOOQ/src/main/java/org/jooq/ExecuteContext.java
index c956037deb..bd8653e59e 100644
--- a/jOOQ/src/main/java/org/jooq/ExecuteContext.java
+++ b/jOOQ/src/main/java/org/jooq/ExecuteContext.java
@@ -66,11 +66,31 @@ public interface ExecuteContext extends Configuration {
/**
* The jOOQ {@link Query} that is being executed or null if the
* query is unknown or if there was no jOOQ Query
+ *
+ * If {@link #batchQueries()} returns several Query objects,
+ * this will always return the currently rendered / prepared
+ * Query, or null, if no Query is
+ * currently being rendered / prepared
*
* @see #routine()
+ * @see #batchQueries()
*/
Query query();
+ /**
+ * The jOOQ {@link Query} objects that are being executed in batch mode, or
+ * null if the query is unknown or if there was no jOOQ
+ * Query
+ *
+ * If a single Query is executed in non-batch mode, this will
+ * return an array of length 1, containing that
+ * Query
+ *
+ * @see #query()
+ * @see #routine()
+ */
+ Query[] batchQueries();
+
/**
* The jOOQ {@link Routine} that is being executed or null if
* the query is unknown or if there was no jOOQ Routine
@@ -94,6 +114,19 @@ public interface ExecuteContext extends Configuration {
*/
void sql(String sql);
+ /**
+ * The generated SQL statements that are being executed in batch mode, or
+ * null if the query is unknown or if there was no SQL statement
+ *
+ * If a single Query is executed in non-batch mode, this will
+ * return an array of length 1, containing that
+ * Query
+ *
+ * @see #query()
+ * @see #routine()
+ */
+ String[] batchSQL();
+
/**
* The {@link PreparedStatement} that is being executed or null
* if the statement is unknown or if there was no statement.
diff --git a/jOOQ/src/main/java/org/jooq/ExecuteListener.java b/jOOQ/src/main/java/org/jooq/ExecuteListener.java
index 3c07b0572c..db321b74f6 100644
--- a/jOOQ/src/main/java/org/jooq/ExecuteListener.java
+++ b/jOOQ/src/main/java/org/jooq/ExecuteListener.java
@@ -73,119 +73,152 @@ import org.jooq.tools.StopWatchListener;
*
Use case [2]
* Use case [3]
* Use case [4]
+ * Use case [5]
+ * Use case [6]
*
*
* {@link #start(ExecuteContext)}
- * Yes
- * Yes
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
*
*
* {@link #renderStart(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, Nx (for every query)
+ * Yes, 1x
*
*
* {@link #renderEnd(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, Nx (for every query)
+ * Yes, 1x
*
*
* {@link #prepareStart(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, Nx (for every query)
+ * Yes, 1x
*
*
* {@link #prepareEnd(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, Nx (for every query)
+ * Yes, 1x
*
*
* {@link #bindStart(ExecuteContext)}
- * Yes
+ * Yes, 1x
* No
* No
- * Yes
+ * Yes, Nx (for every value set)
+ * Yes, 1x
+ * Yes, 1x
*
*
* {@link #bindEnd(ExecuteContext)}
- * Yes
+ * Yes, 1x
* No
* No
- * Yes
- *
+ * Yes, Nx (for every value set)
+ * Yes, 1x
+ * Yes, 1
*
* {@link #executeStart(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
*
*
* {@link #executeEnd(ExecuteContext)}
- * Yes
- * Yes
+ * Yes, 1x
+ * Yes, 1x
* No
- * Yes
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
*
*
* {@link #fetchStart(ExecuteContext)}
- * Yes
- * Yes
- * Yes
+ * Yes, 1x (Nx for {@link ResultQuery#fetchMany()}
+ * Yes, 1x (Nx for {@link ResultQuery#fetchMany()}
+ * Yes, 1x
+ * No
+ * No
* No
*
*
* {@link #resultStart(ExecuteContext)}
- * Yes
- * Yes
- * Yes
+ * Yes, 1x (Nx for {@link Cursor#fetch(int)}
+ * Yes, 1x (Nx for {@link Cursor#fetch(int)}
+ * Yes, 1x
+ * No
+ * No
* No
*
*
* {@link #recordStart(ExecuteContext)}
*
- * Yes
- * Yes
- * Yes
+ * Yes, Nx
+ * Yes, Nx
+ * Yes, Nx
+ * No
+ * No
* No
*
*
* {@link #recordEnd(ExecuteContext)}
- * Yes
- * Yes
- * Yes
+ * Yes, Nx
+ * Yes, Nx
+ * Yes, Nx
+ * No
+ * No
* No
*
*
* {@link #resultEnd(ExecuteContext)}
- * Yes
- * Yes
- * Yes
+ * Yes, 1x (Nx for {@link Cursor#fetch(int)}
+ * Yes, 1x (Nx for {@link Cursor#fetch(int)}
+ * Yes, 1x
+ * No
+ * No
* No
*
*
* {@link #fetchEnd(ExecuteContext)}
- * Yes
- * Yes
- * Yes
+ * Yes, 1x (Nx for {@link ResultQuery#fetchMany()}
+ * Yes, 1x (Nx for {@link ResultQuery#fetchMany()}
+ * Yes, 1x
+ * No
+ * No
* No
*
*
* {@link #end(ExecuteContext)}
- * Yes
- * Yes
- * Yes
- * No
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
+ * Yes, 1x
*
*
*
@@ -197,6 +230,8 @@ import org.jooq.tools.StopWatchListener;
* {@link StatementType#STATIC_STATEMENT}
* Used with {@link Factory#fetch(ResultSet)} or with
* {@link InsertResultStep#fetch()}
+ * Used with {@link Factory#batch(Query)}
+ * Used with {@link Factory#batch(Query[])}
* Used with a {@link Routine} standalone call
*
*
diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java b/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java
index 4dc2d75d1a..7db8ef92bd 100644
--- a/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java
+++ b/jOOQ/src/main/java/org/jooq/impl/BatchMultiple.java
@@ -37,23 +37,17 @@ package org.jooq.impl;
import java.sql.Connection;
import java.sql.SQLException;
-import java.sql.Statement;
import org.jooq.Batch;
+import org.jooq.ExecuteContext;
+import org.jooq.ExecuteListener;
import org.jooq.Query;
-import org.jooq.tools.JooqLogger;
-import org.jooq.tools.StopWatch;
/**
* @author Lukas Eder
*/
class BatchMultiple implements Batch {
- /**
- * Generated UID
- */
- private static final JooqLogger log = JooqLogger.getLogger(BatchMultiple.class);
-
private final Factory create;
private final Query[] queries;
@@ -64,35 +58,40 @@ class BatchMultiple implements Batch {
@Override
public final int[] execute() {
- StopWatch watch = new StopWatch();
Connection connection = create.getConnection();
- Statement statement = null;
- String sql = null;
+
+ ExecuteContext ctx = new DefaultExecuteContext(create, queries);
+ ExecuteListener listener = new ExecuteListeners(ctx);
try {
- statement = connection.createStatement();
+ ctx.statement(new PreparedStatementProxy(connection));
- for (Query query : queries) {
- sql = create.renderInlined(query);
- watch.splitTrace("SQL rendered");
-
- if (log.isDebugEnabled())
- log.debug("Adding batch", sql);
-
- statement.addBatch(sql);
+ String[] batchSQL = ctx.batchSQL();
+ for (int i = 0; i < queries.length; i++) {
+ listener.renderStart(ctx);
+ batchSQL[i] = create.renderInlined(queries[i]);
+ listener.renderEnd(ctx);
}
- int[] result = statement.executeBatch();
- watch.splitTrace("Statement executed");
+ for (String sql : batchSQL) {
+ ctx.sql(sql);
+ listener.prepareStart(ctx);
+ ctx.statement().addBatch(sql);
+ listener.prepareEnd(ctx);
+ ctx.sql(null);
+ }
+
+ listener.executeStart(ctx);
+ int[] result = ctx.statement().executeBatch();
+ listener.executeEnd(ctx);
return result;
}
catch (SQLException e) {
- throw Util.translate("BatchMultiple.execute", sql, e);
+ throw Util.translate("BatchMultiple.execute", ctx.sql(), e);
}
finally {
- Util.safeClose(statement);
- watch.splitDebug("Statement executed");
+ Util.safeClose(listener, ctx);
}
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java b/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java
index bad699bca7..70f790a1a5 100644
--- a/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java
+++ b/jOOQ/src/main/java/org/jooq/impl/BatchSingle.java
@@ -36,26 +36,20 @@
package org.jooq.impl;
import java.sql.Connection;
-import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.jooq.BatchBindStep;
+import org.jooq.ExecuteContext;
+import org.jooq.ExecuteListener;
import org.jooq.Query;
-import org.jooq.tools.JooqLogger;
-import org.jooq.tools.StopWatch;
/**
* @author Lukas Eder
*/
class BatchSingle implements BatchBindStep {
- /**
- * Generated UID
- */
- private static final JooqLogger log = JooqLogger.getLogger(BatchSingle.class);
-
private final Factory create;
private final Query query;
private final List allBindValues;
@@ -74,41 +68,39 @@ class BatchSingle implements BatchBindStep {
@Override
public final int[] execute() {
- StopWatch watch = new StopWatch();
Connection connection = create.getConnection();
- PreparedStatement statement = null;
- String sql = null;
+
+ ExecuteContext ctx = new DefaultExecuteContext(create, query);
+ ExecuteListener listener = new ExecuteListeners(ctx);
try {
+ listener.renderStart(ctx);
+ ctx.sql(create.render(query));
+ listener.renderEnd(ctx);
- sql = create.render(query);
- watch.splitTrace("SQL rendered");
-
- if (log.isDebugEnabled())
- log.debug("Executing query", create.renderInlined(query));
- if (log.isTraceEnabled())
- log.trace("Preparing statement", sql);
-
- statement = connection.prepareStatement(sql);
- watch.splitTrace("Statement prepared");
+ listener.prepareStart(ctx);
+ ctx.statement(connection.prepareStatement(ctx.sql()));
+ listener.prepareEnd(ctx);
for (Object[] bindValues : allBindValues) {
- new DefaultBindContext(create, statement).bindValues(bindValues);
- statement.addBatch();
+ listener.bindStart(ctx);
+ new DefaultBindContext(create, ctx.statement()).bindValues(bindValues);
+ listener.bindEnd(ctx);
+
+ ctx.statement().addBatch();
}
- watch.splitTrace("Variables bound");
- int[] result = statement.executeBatch();
- watch.splitTrace("Statement executed");
+ listener.executeStart(ctx);
+ int[] result = ctx.statement().executeBatch();
+ listener.executeEnd(ctx);
return result;
}
catch (SQLException e) {
- throw Util.translate("BatchSingle.execute", sql, e);
+ throw Util.translate("BatchSingle.execute", ctx.sql(), e);
}
finally {
- Util.safeClose(statement);
- watch.splitDebug("Statement executed");
+ Util.safeClose(listener, ctx);
}
}
}
diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
index 5d43b0e129..e044402edb 100644
--- a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
+++ b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java
@@ -68,6 +68,9 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
private final Routine> routine;
private String sql;
+ private final Query[] batchQueries;
+ private final String[] batchSQL;
+
// Transient attributes
private transient PreparedStatement statement;
private transient ResultSet resultSet;
@@ -75,22 +78,28 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
private transient Result> result;
DefaultExecuteContext(Configuration configuration) {
- this(configuration, null, null);
+ this(configuration, null, null, null);
+ }
+
+ DefaultExecuteContext(Configuration configuration, Query[] batchQueries) {
+ this(configuration, null, batchQueries, null);
}
DefaultExecuteContext(Configuration configuration, Query query) {
- this(configuration, query, null);
+ this(configuration, query, new Query[] { query }, null);
}
DefaultExecuteContext(Configuration configuration, Routine> routine) {
- this(configuration, null, routine);
+ this(configuration, null, null, routine);
}
- private DefaultExecuteContext(Configuration configuration, Query query, Routine> routine) {
+ private DefaultExecuteContext(Configuration configuration, Query query, Query[] batchQueries, Routine> routine) {
super(configuration);
this.query = query;
+ this.batchQueries = batchQueries;
this.routine = routine;
+ this.batchSQL = (batchQueries == null ? null : new String[batchQueries.length]);
}
@Override
@@ -122,6 +131,11 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
return query;
}
+ @Override
+ public final Query[] batchQueries() {
+ return batchQueries;
+ }
+
@Override
public final Routine> routine() {
return routine;
@@ -137,6 +151,11 @@ class DefaultExecuteContext extends AbstractConfiguration implements ExecuteCont
return sql;
}
+ @Override
+ public final String[] batchSQL() {
+ return batchSQL;
+ }
+
@Override
public final void statement(PreparedStatement s) {
this.statement = s;
diff --git a/jOOQ/src/main/java/org/jooq/impl/PreparedStatementProxy.java b/jOOQ/src/main/java/org/jooq/impl/PreparedStatementProxy.java
index ae2c8e2d4f..511b8a75df 100644
--- a/jOOQ/src/main/java/org/jooq/impl/PreparedStatementProxy.java
+++ b/jOOQ/src/main/java/org/jooq/impl/PreparedStatementProxy.java
@@ -87,7 +87,11 @@ class PreparedStatementProxy implements PreparedStatement {
}
private PreparedStatementProxy(Connection connection, String sql, MethodType type) throws SQLException {
- this(connection, sql, type, connection.createStatement());
+ this(connection, sql, type, connection.createStatement());
+ }
+
+ PreparedStatementProxy(Connection connection) throws SQLException {
+ this(connection, null, MethodType.BATCH);
}
PreparedStatementProxy(Connection connection, String sql) throws SQLException {
@@ -161,7 +165,13 @@ class PreparedStatementProxy implements PreparedStatement {
* Corresponds to
* {@link Connection#prepareStatement(String, String[])
*/
- SQL_CN
+ SQL_CN,
+
+ /**
+ * Corresponds to {@link Connection#createStatement()} and
+ * {@link Statement#executeBatch()}
+ */
+ BATCH
}
// ------------------------------------------------------------------------
@@ -364,7 +374,7 @@ class PreparedStatementProxy implements PreparedStatement {
}
// ------------------------------------------------------------------------
- // XXX: Unsupported batch methods
+ // XXX: Supported and unsupported batch methods
// ------------------------------------------------------------------------
@Override
@@ -374,17 +384,17 @@ class PreparedStatementProxy implements PreparedStatement {
@Override
public final void clearBatch() throws SQLException {
- throw new UnsupportedOperationException("Cannot batch execute statements on PreparedStatementProxy");
+ delegate.clearBatch();
}
@Override
public final int[] executeBatch() throws SQLException {
- throw new UnsupportedOperationException("Cannot batch execute statements on PreparedStatementProxy");
+ return delegate.executeBatch();
}
@Override
public final void addBatch(String query) throws SQLException {
- throw new UnsupportedOperationException("Cannot batch execute statements on PreparedStatementProxy");
+ delegate.addBatch(query);
}
// ------------------------------------------------------------------------