diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java index 62d05d56b0..62c4802d1f 100644 --- a/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java +++ b/src/main/java/org/sqlite/jdbc3/JDBC3Statement.java @@ -15,10 +15,13 @@ import org.sqlite.core.DB.ProgressObserver; public abstract class JDBC3Statement extends CoreStatement { + private int queryTimeout; // in seconds, as per the JDBC spec + // PUBLIC INTERFACE ///////////////////////////////////////////// protected JDBC3Statement(SQLiteConnection conn) { super(conn); + queryTimeout = 0; } /** @@ -48,17 +51,27 @@ protected void finalize() throws SQLException { public boolean execute(String sql) throws SQLException { internalClose(); - SQLExtension ext = ExtendedCommand.parse(sql); - if (ext != null) { - ext.execute(db); + int origBusyTimeout = conn.getBusyTimeout(); + if (queryTimeout > 0) + conn.setBusyTimeout(1000 * queryTimeout); - return false; - } + try { + SQLExtension ext = ExtendedCommand.parse(sql); + if (ext != null) { + ext.execute(db); - this.sql = sql; + return false; + } + + this.sql = sql; - db.prepare(this); - return exec(); + db.prepare(this); + return exec(); + } + finally { + if (queryTimeout > 0) + conn.setBusyTimeout(origBusyTimeout); + } } /** @@ -78,14 +91,24 @@ public ResultSet executeQuery(String sql) throws SQLException { internalClose(); this.sql = sql; - db.prepare(this); + int origBusyTimeout = conn.getBusyTimeout(); + if (queryTimeout > 0) + conn.setBusyTimeout(1000 * queryTimeout); - if (!exec()) { - internalClose(); - throw new SQLException("query does not return ResultSet", "SQLITE_DONE", SQLITE_DONE); - } + try { + db.prepare(this); + + if (!exec()) { + internalClose(); + throw new SQLException("query does not return ResultSet", "SQLITE_DONE", SQLITE_DONE); + } - return getResultSet(); + return getResultSet(); + } + finally { + if (queryTimeout > 0) + conn.setBusyTimeout(origBusyTimeout); + } } static class BackupObserver implements ProgressObserver @@ -102,28 +125,38 @@ public int executeUpdate(String sql) throws SQLException { internalClose(); this.sql = sql; - int changes = 0; - SQLExtension ext = ExtendedCommand.parse(sql); - if (ext != null) { - // execute extended command - ext.execute(db); - } - else { - try { - changes = db.total_changes(); - - // directly invokes the exec API to support multiple SQL statements - int statusCode = db._exec(sql); - if (statusCode != SQLITE_OK) - throw DB.newSQLException(statusCode, ""); + int origBusyTimeout = conn.getBusyTimeout(); + if (queryTimeout > 0) + conn.setBusyTimeout(1000 * queryTimeout); - changes = db.total_changes() - changes; + try { + int changes = 0; + SQLExtension ext = ExtendedCommand.parse(sql); + if (ext != null) { + // execute extended command + ext.execute(db); } - finally { - internalClose(); + else { + try { + changes = db.total_changes(); + + // directly invokes the exec API to support multiple SQL statements + int statusCode = db._exec(sql); + if (statusCode != SQLITE_OK) + throw DB.newSQLException(statusCode, ""); + + changes = db.total_changes() - changes; + } + finally { + internalClose(); + } } + return changes; + } + finally { + if (queryTimeout > 0) + conn.setBusyTimeout(origBusyTimeout); } - return changes; } /** @@ -257,7 +290,7 @@ public void cancel() throws SQLException { * @see java.sql.Statement#getQueryTimeout() */ public int getQueryTimeout() throws SQLException { - return conn.getBusyTimeout(); + return queryTimeout; } /** @@ -266,7 +299,7 @@ public int getQueryTimeout() throws SQLException { public void setQueryTimeout(int seconds) throws SQLException { if (seconds < 0) throw new SQLException("query timeout must be >= 0"); - conn.setBusyTimeout(1000 * seconds); + queryTimeout = seconds; } // TODO: write test