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 ...@@ -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. * Registers the given OUT parameter.
* *
......
...@@ -56,7 +56,7 @@ import org.h2.value.ValueTimestamp; ...@@ -56,7 +56,7 @@ import org.h2.value.ValueTimestamp;
* Represents a prepared statement. * Represents a prepared statement.
*/ */
public class JdbcPreparedStatement extends JdbcStatement implements public class JdbcPreparedStatement extends JdbcStatement implements
PreparedStatement { PreparedStatement, JdbcPreparedStatementBackwardsCompat {
protected CommandInterface command; protected CommandInterface command;
private final String sqlStatement; private final String sqlStatement;
...@@ -156,6 +156,38 @@ public class JdbcPreparedStatement extends JdbcStatement implements ...@@ -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 { private int executeUpdateInternal() throws SQLException {
closeOldResultSet(); closeOldResultSet();
synchronized (session) { synchronized (session) {
...@@ -290,6 +322,22 @@ public class JdbcPreparedStatement extends JdbcStatement implements ...@@ -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. * Calling this method is not legal on a PreparedStatement.
* *
...@@ -1307,6 +1355,25 @@ public class JdbcPreparedStatement extends JdbcStatement implements ...@@ -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. * Calling this method is not legal on a PreparedStatement.
...@@ -1329,6 +1396,27 @@ public class JdbcPreparedStatement extends JdbcStatement implements ...@@ -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. * Calling this method is not legal on a PreparedStatement.
* *
...@@ -1351,6 +1439,28 @@ public class JdbcPreparedStatement extends JdbcStatement implements ...@@ -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. * 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 ...@@ -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 { private int executeUpdateInternal(String sql) throws SQLException {
checkClosedForWrite(); checkClosedForWrite();
try { try {
...@@ -246,6 +273,25 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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. * Closes this statement.
* All result sets that where created by this statement * All result sets that where created by this statement
...@@ -375,6 +421,23 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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. * Gets the maximum number of rows for a ResultSet.
* *
...@@ -395,6 +458,26 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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. * Sets the number of rows suggested to read in one step.
* This value cannot be higher than the maximum rows (setMaxRows) * This value cannot be higher than the maximum rows (setMaxRows)
...@@ -696,6 +779,23 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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 * 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 * 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 ...@@ -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. * Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally. * This method just calls executeUpdate(String sql) internally.
...@@ -822,6 +934,31 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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. * Executes a statement and returns the update count.
* This method just calls executeUpdate(String sql) internally. * This method just calls executeUpdate(String sql) internally.
...@@ -847,6 +984,31 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -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. * Executes a statement and returns the update count.
* This method just calls execute(String sql) internally. * This method just calls execute(String sql) internally.
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
*/ */
package org.h2.jdbc; package org.h2.jdbc;
import java.sql.SQLException;
/** /**
* Allows us to compile on older platforms, while still implementing the methods * Allows us to compile on older platforms, while still implementing the methods
* from the newer JDBC API. * from the newer JDBC API.
...@@ -13,4 +15,21 @@ public interface JdbcStatementBackwardsCompat { ...@@ -13,4 +15,21 @@ public interface JdbcStatementBackwardsCompat {
// compatibility interface // 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; ...@@ -11,11 +11,14 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Savepoint; import java.sql.Savepoint;
import java.sql.Statement; import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.jdbc.JdbcPreparedStatementBackwardsCompat;
import org.h2.jdbc.JdbcStatement; import org.h2.jdbc.JdbcStatement;
import org.h2.jdbc.JdbcStatementBackwardsCompat;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.New; import org.h2.util.New;
...@@ -209,6 +212,7 @@ public class TestStatement extends TestBase { ...@@ -209,6 +212,7 @@ public class TestStatement extends TestBase {
ResultSet rs; ResultSet rs;
int count; int count;
long largeCount;
boolean result; boolean result;
stat.execute("CREATE TABLE TEST(ID INT)"); stat.execute("CREATE TABLE TEST(ID INT)");
...@@ -256,6 +260,16 @@ public class TestStatement extends TestBase { ...@@ -256,6 +260,16 @@ public class TestStatement extends TestBase {
assertEquals(0, count); assertEquals(0, count);
count = stat.executeUpdate("DELETE FROM TEST WHERE ID=2"); count = stat.executeUpdate("DELETE FROM TEST WHERE ID=2");
assertEquals(1, count); 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). assertThrows(ErrorCode.METHOD_NOT_ALLOWED_FOR_QUERY, stat).
executeUpdate("SELECT * FROM TEST"); executeUpdate("SELECT * FROM TEST");
...@@ -428,6 +442,29 @@ public class TestStatement extends TestBase { ...@@ -428,6 +442,29 @@ public class TestStatement extends TestBase {
assertTrue(rs.next()); assertTrue(rs.next());
assertEquals("World", rs.getString("name")); assertEquals("World", rs.getString("name"));
assertFalse(rs.next()); 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"); stat.execute("drop table test");
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论