Unverified 提交 b5341bb5 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #718 from katzyn/LargeUpdate

Partial fix for #495
......@@ -82,6 +82,36 @@ public class JdbcCallableStatement extends JdbcPreparedStatement implements
}
}
/**
* Executes a statement (insert, update, delete, create, drop)
* and returns the update count.
* If another result set exists for this statement, this will be closed
* (even if this statement fails).
*
* If auto commit is on, this statement will be committed.
* If the statement is a DDL statement (create, drop, alter) and does not
* throw an exception, the current transaction (if any) is committed after
* executing the statement.
*
* @return the update count (number of row affected by an insert, update or
* delete, or 0 if no rows or the statement was a create, drop,
* commit or rollback)
* @throws SQLException if this object is closed or invalid
*/
@Override
public long executeLargeUpdate() throws SQLException {
try {
checkClosed();
if (command.isQuery()) {
super.executeQuery();
return 0;
}
return super.executeLargeUpdate();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Registers the given OUT parameter.
*
......
......@@ -56,7 +56,7 @@ import org.h2.value.ValueTimestamp;
* Represents a prepared statement.
*/
public class JdbcPreparedStatement extends JdbcStatement implements
PreparedStatement {
PreparedStatement, JdbcPreparedStatementBackwardsCompat {
protected CommandInterface command;
private final String sqlStatement;
......@@ -156,6 +156,38 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
}
/**
* Executes a statement (insert, update, delete, create, drop)
* and returns the update count.
* If another result set exists for this statement, this will be closed
* (even if this statement fails).
*
* If auto commit is on, this statement will be committed.
* If the statement is a DDL statement (create, drop, alter) and does not
* throw an exception, the current transaction (if any) is committed after
* executing the statement.
*
* @return the update count (number of row affected by an insert, update or
* delete, or 0 if no rows or the statement was a create, drop,
* commit or rollback)
* @throws SQLException if this object is closed or invalid
*/
@Override
public long executeLargeUpdate() throws SQLException {
try {
debugCodeCall("executeLargeUpdate");
checkClosedForWrite();
batchIdentities = null;
try {
return executeUpdateInternal();
} finally {
afterWriting();
}
} catch (Exception e) {
throw logAndConvert(e);
}
}
private int executeUpdateInternal() throws SQLException {
closeOldResultSet();
synchronized (session) {
......@@ -290,6 +322,22 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
* @param sql ignored
* @throws SQLException Unsupported Feature
*/
@Override
public long executeLargeUpdate(String sql) throws SQLException {
try {
debugCodeCall("executeLargeUpdate", sql);
throw DbException.get(ErrorCode.METHOD_NOT_ALLOWED_FOR_PREPARED_STATEMENT);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
......@@ -1307,6 +1355,25 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
* @param sql ignored
* @param autoGeneratedKeys ignored
* @throws SQLException Unsupported Feature
*/
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys)
throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate("+quote(sql)+", "+autoGeneratedKeys+");");
}
throw DbException.get(ErrorCode.METHOD_NOT_ALLOWED_FOR_PREPARED_STATEMENT);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Calling this method is not legal on a PreparedStatement.
......@@ -1329,6 +1396,27 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
* @param sql ignored
* @param columnIndexes ignored
* @throws SQLException Unsupported Feature
*/
@Override
public long executeLargeUpdate(String sql, int[] columnIndexes)
throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate(" + quote(sql) + ", " +
quoteIntArray(columnIndexes) + ");");
}
throw DbException.get(ErrorCode.METHOD_NOT_ALLOWED_FOR_PREPARED_STATEMENT);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
......@@ -1351,6 +1439,28 @@ public class JdbcPreparedStatement extends JdbcStatement implements
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
* @param sql ignored
* @param columnNames ignored
* @throws SQLException Unsupported Feature
*/
@Override
public long executeLargeUpdate(String sql, String[] columnNames)
throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate(" + quote(sql) + ", " +
quoteArray(columnNames) + ");");
}
throw DbException.get(
ErrorCode.METHOD_NOT_ALLOWED_FOR_PREPARED_STATEMENT);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Calling this method is not legal on a PreparedStatement.
*
......
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jdbc;
import java.sql.SQLException;
/**
* Allows us to compile on older platforms, while still implementing the methods
* from the newer JDBC API.
*/
public interface JdbcPreparedStatementBackwardsCompat {
// compatibility interface
// JDBC 4.2 (incomplete)
long executeLargeUpdate() throws SQLException;
}
......@@ -124,6 +124,33 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Executes a statement (insert, update, delete, create, drop)
* and returns the update count.
* If another result set exists for this statement, this will be closed
* (even if this statement fails).
*
* If auto commit is on, this statement will be committed.
* If the statement is a DDL statement (create, drop, alter) and does not
* throw an exception, the current transaction (if any) is committed after
* executing the statement.
*
* @param sql the SQL statement
* @return the update count (number of row affected by an insert,
* update or delete, or 0 if no rows or the statement was a
* create, drop, commit or rollback)
* @throws SQLException if a database error occurred or a
* select statement was executed
*/
public long executeLargeUpdate(String sql) throws SQLException {
try {
debugCodeCall("executeLargeUpdate", sql);
return executeUpdateInternal(sql);
} catch (Exception e) {
throw logAndConvert(e);
}
}
private int executeUpdateInternal(String sql) throws SQLException {
checkClosedForWrite();
try {
......@@ -246,6 +273,25 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Returns the last update count of this statement.
*
* @return the update count (number of row affected by an insert, update or
* delete, or 0 if no rows or the statement was a create, drop,
* commit or rollback; -1 if the statement was a select).
* @throws SQLException if this object is closed or invalid
*/
@Override
public long getLargeUpdateCount() throws SQLException {
try {
debugCodeCall("getLargeUpdateCount");
checkClosed();
return updateCount;
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Closes this statement.
* All result sets that where created by this statement
......@@ -375,6 +421,23 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Gets the maximum number of rows for a ResultSet.
*
* @return the number of rows where 0 means no limit
* @throws SQLException if this object is closed
*/
@Override
public long getLargeMaxRows() throws SQLException {
try {
debugCodeCall("getLargeMaxRows");
checkClosed();
return maxRows;
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Gets the maximum number of rows for a ResultSet.
*
......@@ -395,6 +458,26 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Gets the maximum number of rows for a ResultSet.
*
* @param maxRows the number of rows where 0 means no limit
* @throws SQLException if this object is closed
*/
@Override
public void setLargeMaxRows(long maxRows) throws SQLException {
try {
debugCodeCall("setLargeMaxRows", maxRows);
checkClosed();
if (maxRows < 0) {
throw DbException.getInvalidValueException("maxRows", maxRows);
}
this.maxRows = maxRows <= Integer.MAX_VALUE ? (int) maxRows : 0;
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Sets the number of rows suggested to read in one step.
* This value cannot be higher than the maximum rows (setMaxRows)
......@@ -696,6 +779,23 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Executes the batch.
* If one of the batched statements fails, this database will continue.
*
* @return the array of update counts
*/
@Override
public long[] executeLargeBatch() throws SQLException {
int[] intResult = executeBatch();
int count = intResult.length;
long[] longResult = new long[count];
for (int i = 0; i < count; i++) {
longResult[i] = intResult[i];
}
return longResult;
}
/**
* Return a result set that contains the last generated auto-increment key
* for this connection, if there was one. If no key was generated by the
......@@ -797,6 +897,18 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
@Override
public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate("+quote(sql)+", "+autoGeneratedKeys+");");
}
return executeUpdateInternal(sql);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally.
......@@ -822,6 +934,31 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally.
* The method getGeneratedKeys supports at most one columns and row.
*
* @param sql the SQL statement
* @param columnIndexes ignored
* @return the update count (number of row affected by an insert,
* update or delete, or 0 if no rows or the statement was a
* create, drop, commit or rollback)
* @throws SQLException if a database error occurred or a
* select statement was executed
*/
@Override
public long executeLargeUpdate(String sql, int columnIndexes[]) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate("+quote(sql)+", "+quoteIntArray(columnIndexes)+");");
}
return executeUpdateInternal(sql);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally.
......@@ -847,6 +984,31 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
}
}
/**
* Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally.
* The method getGeneratedKeys supports at most one columns and row.
*
* @param sql the SQL statement
* @param columnNames ignored
* @return the update count (number of row affected by an insert,
* update or delete, or 0 if no rows or the statement was a
* create, drop, commit or rollback)
* @throws SQLException if a database error occurred or a
* select statement was executed
*/
@Override
public long executeLargeUpdate(String sql, String columnNames[]) throws SQLException {
try {
if (isDebugEnabled()) {
debugCode("executeLargeUpdate("+quote(sql)+", "+quoteArray(columnNames)+");");
}
return executeUpdateInternal(sql);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Executes a statement and returns the update count.
* This method just calls execute(String sql) internally.
......
......@@ -5,6 +5,8 @@
*/
package org.h2.jdbc;
import java.sql.SQLException;
/**
* Allows us to compile on older platforms, while still implementing the methods
* from the newer JDBC API.
......@@ -13,4 +15,21 @@ public interface JdbcStatementBackwardsCompat {
// compatibility interface
// JDBC 4.2
long getLargeUpdateCount() throws SQLException;
void setLargeMaxRows(long max) throws SQLException;
long getLargeMaxRows() throws SQLException;
long[] executeLargeBatch() throws SQLException;
long executeLargeUpdate(String sql) throws SQLException;
long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException;
long executeLargeUpdate(String sql, int columnIndexes[]) throws SQLException;
long executeLargeUpdate(String sql, String columnNames[]) throws SQLException;
}
......@@ -11,11 +11,14 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap;
import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties;
import org.h2.jdbc.JdbcPreparedStatementBackwardsCompat;
import org.h2.jdbc.JdbcStatement;
import org.h2.jdbc.JdbcStatementBackwardsCompat;
import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase;
import org.h2.util.New;
......@@ -209,6 +212,7 @@ public class TestStatement extends TestBase {
ResultSet rs;
int count;
long largeCount;
boolean result;
stat.execute("CREATE TABLE TEST(ID INT)");
......@@ -256,6 +260,16 @@ public class TestStatement extends TestBase {
assertEquals(0, count);
count = stat.executeUpdate("DELETE FROM TEST WHERE ID=2");
assertEquals(1, count);
JdbcStatementBackwardsCompat statBC = (JdbcStatementBackwardsCompat) stat;
largeCount = statBC.executeLargeUpdate("DELETE FROM TEST WHERE ID=-1");
assertEquals(0, largeCount);
assertEquals(0, statBC.getLargeUpdateCount());
largeCount = statBC.executeLargeUpdate("INSERT INTO TEST(VALUE,ID) VALUES('JDBC',2)");
assertEquals(1, largeCount);
assertEquals(1, statBC.getLargeUpdateCount());
largeCount = statBC.executeLargeUpdate("DELETE FROM TEST WHERE ID=2");
assertEquals(1, largeCount);
assertEquals(1, statBC.getLargeUpdateCount());
assertThrows(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY, stat).
executeUpdate("SELECT * FROM TEST");
......@@ -428,6 +442,29 @@ public class TestStatement extends TestBase {
assertTrue(rs.next());
assertEquals("World", rs.getString("name"));
assertFalse(rs.next());
ps = conn.prepareStatement("insert into test values(?, ?)");
ps.setInt(1, 3);
ps.setString(2, "v3");
ps.addBatch();
ps.setInt(1, 4);
ps.setString(2, "v4");
ps.addBatch();
assertTrue(Arrays.equals(new int[] {1, 1}, ps.executeBatch()));
ps.setInt(1, 5);
ps.setString(2, "v5");
ps.addBatch();
ps.setInt(1, 6);
ps.setString(2, "v6");
ps.addBatch();
assertTrue(Arrays.equals(new long[] {1, 1}, ((JdbcStatementBackwardsCompat) ps).executeLargeBatch()));
ps.setInt(1, 7);
ps.setString(2, "v7");
assertEquals(1, ps.executeUpdate());
assertEquals(1, ps.getUpdateCount());
ps.setInt(1, 8);
ps.setString(2, "v8");
assertEquals(1, ((JdbcPreparedStatementBackwardsCompat) ps).executeLargeUpdate());
assertEquals(1, ((JdbcStatementBackwardsCompat) ps).getLargeUpdateCount());
stat.execute("drop table test");
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论