changeset 14:3fa949cbc783

Implemented Statement methods: getQueryTimeout() and setQueryTimeout(int seconds). getQueryTimeout() used to always return 0, now it returns the query timeout retrieved from the server. setQueryTimeout(int seconds) used to always throw SQLException: query time outs not supported. Now it sets the query timeout for the current connection/session on the server. This fixes bug 3357
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 06 Oct 2016 16:47:54 +0200 (2016-10-06)
parents 749e3cf8b2aa
children 6e48d0fae766
files ChangeLog src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java tests/BugSetQueryTimeout_Bug_3357.java tests/build.xml
diffstat 4 files changed, 84 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,14 @@
 # ChangeLog file for java
 # This file is updated with Maddlog
 
+* Thu Oct  6 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Implemented Statement methods: getQueryTimeout() and setQueryTimeout(int
+  seconds).  getQueryTimeout() used to always return 0, now it returns the
+  query timeout retrieved from the server.  setQueryTimeout(int seconds)
+  used to always throw SQLException: query time outs not supported.
+  Now it sets the query timeout for the current connection/session on
+  the server.
+
 * Thu Sep 29 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
 - Corrected ResultSet methods: getByte(), getBigDecimal(), getShort(),
   getInt(), getLong(), getFloat() and getDouble() in case the conversion
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
@@ -826,9 +826,6 @@ public class MonetStatement extends Mone
 	 * Statement object to execute.  If the limit is exceeded, a
 	 * SQLException is thrown.
 	 *
-	 * For MonetDB this method always returns zero, as no query
-	 * cancelling is possible.
-	 *
 	 * @return the current query timeout limit in seconds; zero means
 	 *         there is no limit
 	 * @throws SQLException if a database access error occurs
@@ -836,7 +833,26 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public int getQueryTimeout() throws SQLException {
-		return 0;
+		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)
 	}
 
 	/**
@@ -1080,9 +1096,6 @@ public class MonetStatement extends Mone
 	 * object to execute to the given number of seconds. If the limit is
 	 * exceeded, an SQLException is thrown.
 	 *
-	 * MonetDB does not support cancelling running queries, hence this
-	 * method does not do anything.
-	 *
 	 * @param seconds the new query timeout limit in seconds; zero means
 	 *        there is no limit
 	 * @throws SQLException if a database access error occurs or the
@@ -1092,8 +1105,18 @@ public class MonetStatement extends Mone
 	public void setQueryTimeout(int seconds) throws SQLException {
 		if (seconds < 0)
 			throw new SQLException("Illegal timeout value: " + seconds, "M1M05");
-		if (seconds > 0)
-			addWarning("setQueryTimeout: query time outs not supported", "01M24");
+
+		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();
+			}
+		}
 	}
 
 	//== 1.6 methods (JDBC 4.0)
new file mode 100644
--- /dev/null
+++ b/tests/BugSetQueryTimeout_Bug_3357.java
@@ -0,0 +1,37 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0.  If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
+ */
+
+import java.sql.*;
+
+public class BugSetQueryTimeout_Bug_3357 {
+	public static void main(String[] args) throws Exception {
+		Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");
+		Connection con = DriverManager.getConnection(args[0]);
+		Statement st = con.createStatement();
+		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());
+		} catch (SQLException se) {
+			System.out.println("setQueryTimeout(timeout_value) throws: " + se);
+		} finally {
+			st.close();
+		}
+		con.close();
+	}
+}
--- a/tests/build.xml
+++ b/tests/build.xml
@@ -128,6 +128,7 @@ Copyright 1997 - July 2008 CWI, August 2
     <antcall target="BugConcurrent_clients_SF_1504657" />
     <antcall target="BugConcurrent_sequences" />
     <antcall target="BugDatabaseMetaData_Bug_3356" />
+    <antcall target="BugSetQueryTimeout_Bug_3357" />
     <antcall target="BugDecimalRound_Bug_3561" />
   </target>
 
@@ -343,4 +344,10 @@ Copyright 1997 - July 2008 CWI, August 2
     </antcall>
   </target>
 
+  <target name="BugSetQueryTimeout_Bug_3357">
+    <antcall target="test_class">
+      <param name="test.class" value="BugSetQueryTimeout_Bug_3357" />
+    </antcall>
+  </target>
+
 </project>