Mercurial > hg > monetdb-java
changeset 249:46385d8ff8c9
Improve the implementation of Statement methods getQueryTimeout() and setQueryTimeout().
Previously the timeout would be set directly on the server implying all next statements within the connection session would use the new timeout setting.
However the timeout in JDBC can be set per Statement and be different for different Statements. This behavior is now implemented.
The implementation is now similar to the implementation in the ODBC driver code.
author | Martin van Dinther <martin.van.dinther@monetdbsolutions.com> |
---|---|
date | Thu, 30 Aug 2018 16:55:04 +0200 (2018-08-30) |
parents | 55375d489024 |
children | 3038e60bdca1 |
files | src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java tests/BugSetQueryTimeout_Bug_3357.java |
diffstat | 3 files changed, 44 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -156,6 +156,9 @@ public class MonetConnection private boolean queriedCommentsTable = false; private boolean hasCommentsTable = false; + /** The last set query timeout on the server as used by Statement and PreparedStatement (and CallableStatement in future) */ + protected int lastSetQueryTimeout = 0; // 0 means no timeout, which is the default on the server + /** * Constructor of a Connection for MonetDB. At this moment the
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -64,9 +64,10 @@ public class MonetStatement protected boolean closed; /** Whether the application wants this Statement object to be pooled */ protected boolean poolable; - /** Whether this Statement should be closed if the last ResultSet - * closes */ + /** Whether this Statement should be closed if the last ResultSet closes */ private boolean closeOnCompletion = false; + /** The timeout (in sec) for the query to return, 0 means no timeout */ + private int queryTimeout = 0; /** The size of the blocks of results to ask for at the server */ private int fetchSize = 0; /** The maximum number of rows to return in a ResultSet */ @@ -106,6 +107,7 @@ public class MonetStatement this.connection = connection; this.resultSetType = resultSetType; this.resultSetConcurrency = resultSetConcurrency; + this.queryTimeout = connection.lastSetQueryTimeout; // check our limits, and generate warnings as appropriate if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY) { @@ -506,6 +508,25 @@ public class MonetStatement lastResponseList = null; } + if (queryTimeout != connection.lastSetQueryTimeout) { + // set requested/changed queryTimeout on the server side first + Statement st = null; + try { + st = connection.createStatement(); + String callstmt = "CALL \"sys\".\"settimeout\"(" + queryTimeout + ")"; + // for debug: System.out.println("Before: " + callstmt); + st.execute(callstmt); + // for debug: System.out.println("After : " + callstmt); + connection.lastSetQueryTimeout = queryTimeout; + } + /* do not catch SQLException here, as we want to know it when it fails */ + finally { + if (st != null) { + st.close(); + } + } + } + // create a container for the result lastResponseList = connection.new ResponseList( fetchSize, @@ -833,27 +854,8 @@ public class MonetStatement * @see #setQueryTimeout(int) */ @Override - public int getQueryTimeout() throws SQLException { - Statement st = null; - ResultSet rs = null; - try { - st = connection.createStatement(); - rs = st.executeQuery("SELECT \"querytimeout\" FROM \"sys\".\"sessions\"() WHERE \"active\""); - if (rs != null && rs.next()) { - // MonetDB stores querytimeout in a bigint, so correctly deal with big int values - long timeout = rs.getLong(1); - return (timeout > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) timeout; - } - /* do not catch SQLException here, as we want to know it when it fails */ - } finally { - if (rs != null) { - rs.close(); - } - if (st != null) { - st.close(); - } - } - return 0; // in case the query didn't return a result (which should normally never happen) + public int getQueryTimeout() { + return queryTimeout; } /** @@ -1108,18 +1110,7 @@ public class MonetStatement public void setQueryTimeout(int seconds) throws SQLException { if (seconds < 0) throw new SQLException("Illegal timeout value: " + seconds, "M1M05"); - - Statement st = null; - try { - st = connection.createStatement(); - // CALL "sys"."settimeout"(int_value) - st.execute("CALL \"sys\".\"settimeout\"(" + seconds + ")"); - /* do not catch SQLException here, as we want to know it when it fails */ - } finally { - if (st != null) { - st.close(); - } - } + queryTimeout = seconds; } //== 1.6 methods (JDBC 4.0)
--- a/tests/BugSetQueryTimeout_Bug_3357.java +++ b/tests/BugSetQueryTimeout_Bug_3357.java @@ -16,17 +16,12 @@ public class BugSetQueryTimeout_Bug_3357 try { System.out.println("QueryTimeout = " + st.getQueryTimeout()); - st.setQueryTimeout(123); - System.out.println("QueryTimeout = " + st.getQueryTimeout()); - - st.setQueryTimeout(2134567890); - System.out.println("QueryTimeout = " + st.getQueryTimeout()); - - st.setQueryTimeout(0); - System.out.println("QueryTimeout = " + st.getQueryTimeout()); - - st.setQueryTimeout(-1); // to generate an SQLException as negative timeouts are invalid - System.out.println("QueryTimeout = " + st.getQueryTimeout()); + testTimeout(st, 123); + testTimeout(st, 123); + testTimeout(st, 2134567890); + testTimeout(st, 0); + testTimeout(st, 0); + testTimeout(st, -1); // to generate an SQLException as negative timeouts are invalid } catch (SQLException se) { System.out.println("setQueryTimeout(timeout_value) throws: " + se); } finally { @@ -34,4 +29,13 @@ public class BugSetQueryTimeout_Bug_3357 } con.close(); } + + private static void testTimeout(Statement st, int secs) throws SQLException { + st.setQueryTimeout(secs); + // as the call to set the timeout is delayed till a statement is executed, issue a select statment + ResultSet rs = st.executeQuery("SELECT " + secs); + if (rs != null) + rs.close(); + System.out.println("QueryTimeout = " + st.getQueryTimeout()); + } }