Skip to content
Permalink
Browse files

[jdbc-driver] Batch support on statement and prepared statement.

  • Loading branch information
cchantep
cchantep committed Mar 8, 2014
1 parent ce8a913 commit 2a2093606f5c4582efa2fea4aa18de357f4b8a1c
@@ -1,15 +1,19 @@
package acolyte;

import java.util.Collections;
import java.util.Properties;
import java.util.ArrayList;
import java.util.List;

import java.sql.SQLFeatureNotSupportedException;
import java.sql.BatchUpdateException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Connection;
import java.sql.ResultSet;

import org.apache.commons.lang3.tuple.ImmutableTriple;

import acolyte.StatementHandler.Parameter;

/**
@@ -100,6 +104,11 @@
*/
protected int fetchSize = 0;

/**
* Batch elements
*/
private final ArrayList<String> batch;

/**
* Owner connection
*/
@@ -114,6 +123,7 @@
protected AbstractStatement() {
this.connection = null;
this.handler = null;
this.batch = new ArrayList<String>();
} // end of <init>

/**
@@ -134,6 +144,7 @@ protected AbstractStatement(final acolyte.Connection connection,

this.connection = connection;
this.handler = handler;
this.batch = new ArrayList<String>();
} // end of <init>

// ---
@@ -147,13 +158,19 @@ public ResultSet executeQuery(final String sql) throws SQLException {
this.updateCount = -1;
this.generatedKeys = NO_GENERATED_KEY;

final QueryResult res = this.handler.whenSQLQuery(sql, NO_PARAMS);

this.warning = res.getWarning();

return (this.result = res.getRowList().
resultSet(this.maxRows).withStatement(this));

try {
final QueryResult res = this.handler.whenSQLQuery(sql, NO_PARAMS);

this.warning = res.getWarning();

return (this.result = res.getRowList().
resultSet(this.maxRows).withStatement(this));

} catch (SQLException se) {
throw se;
} catch (Exception e) {
throw new SQLException(e);
} // end of catch
} // end of executeQuery

/**
@@ -374,26 +391,51 @@ public int getResultSetType() throws SQLException {

/**
* {@inheritDoc}
* @throws java.sql.SQLException Batch is not supported
*/
public void addBatch(final String sql) throws SQLException {
throw new SQLException("Batch is not supported");
checkClosed();

this.batch.add(sql);
} // end of addBatch

/**
* {@inheritDoc}
* @throws java.sql.SQLException Batch is not supported
*/
public void clearBatch() throws SQLException {
throw new SQLException("Batch is not supported");
this.batch.clear();
} // end of clearBatch

/**
* {@inheritDoc}
* @throws java.sql.SQLException Batch is not supported
*/
public int[] executeBatch() throws SQLException {
throw new SQLException("Batch is not supported");
final int[] cs = new int[batch.size()];
java.util.Arrays.fill(cs, EXECUTE_FAILED);

final boolean cont =
"true".equals(connection.getProperties().
get("acolyte.batch.continueOnError"));

SQLException firstEx = null; // if |cont| is true
SQLException lastEx = null;

int i = 0;
for (final String sql : batch) {
try {
cs[i++] = update(sql, NO_GENERATED_KEYS).left;
} catch (SQLException se) {
if (!cont) throw new BatchUpdateException(se.getMessage(), se.getSQLState(), se.getErrorCode(), cs, se.getCause());
else {
if (firstEx == null) firstEx = se;
if (lastEx != null) lastEx.setNextException(se);
lastEx = se;
} // end of else
} // end of catch
} // end of for

if (firstEx != null) throw new BatchUpdateException(firstEx.getMessage(), firstEx.getSQLState(), firstEx.getErrorCode(), cs, firstEx.getCause());

return cs;
} // end of executeBatch

/**
@@ -429,22 +471,42 @@ public ResultSet getGeneratedKeys() throws SQLException {
public int executeUpdate(final String sql, final int autoGeneratedKeys)
throws SQLException {

checkClosed();

this.result = null;

final UpdateResult res = this.handler.whenSQLUpdate(sql, NO_PARAMS);
final ImmutableTriple<Integer,ResultSet,SQLWarning> res =
update(sql, autoGeneratedKeys);

this.warning = res.getWarning();
this.generatedKeys =
(res.generatedKeys == null
|| autoGeneratedKeys == NO_GENERATED_KEYS)
? RowLists.stringList().resultSet()/* empty ResultSet */
: res.generatedKeys.resultSet();
this.warning = res.right;
this.generatedKeys = res.middle;

return (this.updateCount = res.getUpdateCount());
return (this.updateCount = res.left);
} // end of executeUpdate

/**
* Executes update.
* @return Triple of update count, generated keys (or null)
* and optional warning
*/
private ImmutableTriple<Integer,ResultSet,SQLWarning> update(final String sql, final int autoGeneratedKeys) throws SQLException {

checkClosed();

try {
final UpdateResult res = this.handler.whenSQLUpdate(sql, NO_PARAMS);
final SQLWarning w = res.getWarning();
final ResultSet k = (res.generatedKeys == null
|| autoGeneratedKeys == NO_GENERATED_KEYS)
? RowLists.stringList().resultSet()/* empty ResultSet */
: res.generatedKeys.resultSet();

return ImmutableTriple.of(res.getUpdateCount(), k, w);
} catch (SQLException se) {
throw se;
} catch (Exception e) {
throw new SQLException(e);
} // end of catch
} // end of update

/**
* {@inheritDoc}
*/
@@ -18,9 +18,11 @@
import java.net.URL;

import java.sql.SQLFeatureNotSupportedException;
import java.sql.BatchUpdateException;
import java.sql.ParameterMetaData;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.sql.SQLXML;
@@ -34,6 +36,7 @@
import java.sql.Time;
import java.sql.Ref;

import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.ImmutablePair;

import acolyte.ParameterMetaData.ParameterDef;
@@ -106,6 +109,11 @@
private final TreeMap<Integer,Parameter> parameters =
new TreeMap<Integer,Parameter>();

/**
* Batch elements
*/
private final ArrayList<ImmutablePair<String,TreeMap<Integer,Parameter>>> batch;

// --- Constructors ---

/**
@@ -127,6 +135,7 @@ protected PreparedStatement(final acolyte.Connection connection,

this.sql = sql;
this.query = handler.isQuery(sql);
this.batch = new ArrayList<ImmutablePair<String,TreeMap<Integer,Parameter>>>();
} // end of <init>

// ---
@@ -154,19 +163,45 @@ public ResultSet executeQuery() throws SQLException {

// ---

final QueryResult res = this.handler.whenSQLQuery(sql, params);

this.updateCount = -1;
this.warning = res.getWarning();
this.generatedKeys = NO_GENERATED_KEY;

return (this.result = res.getRowList().resultSet().withStatement(this));
try {
final QueryResult res = this.handler.whenSQLQuery(sql, params);

this.updateCount = -1;
this.warning = res.getWarning();
this.generatedKeys = NO_GENERATED_KEY;

return (this.result =
res.getRowList().resultSet().withStatement(this));

} catch (SQLException se) {
throw se;
} catch (Exception e) {
throw new SQLException(e);
} // end of catch
} // end of executeQuery

/**
* {@inheritDoc}
*/
public int executeUpdate() throws SQLException {
this.result = null;

final ImmutableTriple<Integer,ResultSet,SQLWarning> res =
update(parameters);

this.warning = res.right;
this.generatedKeys = res.middle;

return (this.updateCount = res.left);
} // end of executeUpdate

/**
* Executes update.
* @return Triple of update count, generated keys (or null)
* and optional warning
*/
private ImmutableTriple<Integer,ResultSet,SQLWarning> update(final TreeMap<Integer,Parameter> parameters) throws SQLException {

checkClosed();

if (this.query) {
@@ -176,7 +211,7 @@ public int executeUpdate() throws SQLException {
// ---

final ArrayList<Parameter> params =
new ArrayList<Parameter>(this.parameters.values());
new ArrayList<Parameter>(parameters.values());

final int idx = params.indexOf(null);

@@ -186,16 +221,20 @@ public int executeUpdate() throws SQLException {

// ---

final UpdateResult res = this.handler.whenSQLUpdate(sql, params);

this.result = null;
this.warning = res.getWarning();
this.generatedKeys = (res.generatedKeys == null)
? RowLists.stringList().resultSet()/* empty ResultSet */
: res.generatedKeys.resultSet();

return (this.updateCount = res.getUpdateCount());
} // end of executeUpdate
try {
final UpdateResult res = this.handler.whenSQLUpdate(sql, params);
final SQLWarning w = res.getWarning();
final ResultSet k = (res.generatedKeys == null)
? RowLists.stringList().resultSet()/* empty ResultSet */
: res.generatedKeys.resultSet();

return ImmutableTriple.of(res.getUpdateCount(), k, w);
} catch (SQLException se) {
throw se;
} catch (Exception e) {
throw new SQLException(e);
} // end of catch
} // end of update

/**
* {@inheritDoc}
@@ -437,13 +476,63 @@ public boolean execute() throws SQLException {

/**
* {@inheritDoc}
* @throws java.sql.SQLException Batch is not supported
* @see AbstractStatement#addBatch
* @throws java.sql.SQLException As cannot used SQL on already prepared statement.
*/
public void addBatch(final String sql) throws SQLException {
throw new SQLException("Cannot add distinct SQL to prepared statement");
} // end of addBatch

/**
* {@inheritDoc}
*/
public void addBatch() throws SQLException {
throw new SQLException("Batch is not supported");
checkClosed();

batch.add(ImmutablePair.
of(sql, new TreeMap<Integer,Parameter>(parameters)));

} // end of addBatch

/**
* {@inheritDoc}
*/
public void clearBatch() throws SQLException {
this.batch.clear();
} // end of clearBatch

/**
* {@inheritDoc}
*/
public int[] executeBatch() throws SQLException {
final int[] cs = new int[batch.size()];
java.util.Arrays.fill(cs, EXECUTE_FAILED);

final boolean cont =
"true".equals(connection.getProperties().
get("acolyte.batch.continueOnError"));

SQLException firstEx = null; // if |cont| is true
SQLException lastEx = null;

int i = 0;
for (final ImmutablePair<String,TreeMap<Integer,Parameter>> b : batch) {
try {
cs[i++] = update(b.right).left;
} catch (SQLException se) {
if (!cont) throw new BatchUpdateException(se.getMessage(), se.getSQLState(), se.getErrorCode(), cs, se.getCause());
else {
if (firstEx == null) firstEx = se;
if (lastEx != null) lastEx.setNextException(se);
lastEx = se;
} // end of else
} // end of catch
} // end of for

if (firstEx != null) throw new BatchUpdateException(firstEx.getMessage(), firstEx.getSQLState(), firstEx.getErrorCode(), cs, firstEx.getCause());

return cs;
} // end of executeBatch

/**
* {@inheritDoc}
* @throws java.sql.SQLFeatureNotSupportedException

0 comments on commit 2a20936

Please sign in to comment.
You can’t perform that action at this time.