changeset 172:60063c67f9e7 embedded

Merged with default
author Pedro Ferreira <pedro.ferreira@monetdbsolutions.com>
date Tue, 19 Sep 2017 13:49:34 +0200 (2017-09-19)
parents 0f95fee3cf29 (current diff) 296c4a16ef9f (diff)
children 89c285fc0a49
files build.properties pom.xml src/main/java/nl/cwi/monetdb/client/JdbcClient.java src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetDataSource.java src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java tests/Bug_PrepStmtSetString_6382.java tests/Test_PSmetadata.java tests/build.xml
diffstat 25 files changed, 3094 insertions(+), 2485 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags
+++ b/.hgtags
@@ -1,1 +1,3 @@
 80de05f07508fec938845b4a6e05f600bf0b48c0 v2.24
+c43c293f3d5841517cbe0d858108c4da5fb1ec0c v2.26
+a6a2f4ee2d42d7e192f9d8d37f79ea99178d7f2c v2.25
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
 # ChangeLog file for monetdb-java
 # This file is updated with Maddlog
 
+* Thu Sep  7 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Implemented PreparedStatement methods setNCharacterStream(int, Reader)
+  and setNCharacterStream(int, Reader, long).
+
+* Thu Aug 31 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Corrected PreparedStatement methods setString(int, String)
+  and setObject(int, Object, ...) in case the target parameter
+  data type was json or inet or url or uuid.  See also
+  https://www.monetdb.org/bugzilla/show_bug.cgi?id=6382
+
+* Thu Aug 24 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Implemented PreparedStatement method setURL(int, URL).
+- Implemented PreparedStatement method setNString(int, String).
+- The MonetDB JDBC driver code and jdbcclient program are now compiled
+  without debug info and with optimise flag enabled.  The new jar files are
+  now smaller in size.
+
+* Thu Aug 17 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Implemented ResultSet method getNCharacterStream().
+- In class MonetClob implemented methods getCharacterStream()
+  and getCharacterStream(long pos, long length).  Method
+  getCharacterStream() is called by DBeaver to fetch the Clob value.
+  It used to throw a SQLFeatureNotSupportedException with message:
+   "Method getCharacterStream() currently not supported". This caused
+  DBeaver to log the exception and show NULL as the value on screen,
+  which is incorrect.  This has been fixed.
+
+* Fri Jul 28 2017 Sjoerd Mullender <sjoerd@acm.org>
+- Compiled and released new jars: monetdb-jdbc-2.26.jar and updated jdbcclient.jar
+
+* Thu Jul 13 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Corrected implementation of PreparedStatement method
+   setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
+  for the case the targetSqlType is Types.CLOB.
+  See also: https://www.monetdb.org/bugzilla/show_bug.cgi?id=6349
+
--- a/ChangeLog-Archive
+++ b/ChangeLog-Archive
@@ -1,6 +1,25 @@
 # DO NOT EDIT THIS FILE -- MAINTAINED AUTOMATICALLY
 # This file contains past monetdb-java ChangeLog entries
 
+* Fri Jul 28 2017 Sjoerd Mullender <sjoerd@acm.org>
+- Compiled and released new jars: monetdb-jdbc-2.26.jar and updated jdbcclient.jar
+
+* Thu Jul 13 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Corrected implementation of PreparedStatement method
+   setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
+  for the case the targetSqlType is Types.CLOB.
+  See also: https://www.monetdb.org/bugzilla/show_bug.cgi?id=6349
+
+* Thu Mar 30 2017 Sjoerd Mullender <sjoerd@acm.org>
+- Compiled and released new jars: monetdb-jdbc-2.25.jar, monetdb-mcl-1.15.jar
+  and updated jdbcclient.jar
+
+* Thu Mar  9 2017 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Corrected ResultSetMetaData methods getColumnLabel(int), getColomnName(int),
+  getTableName(int) and getSchemaName(int) for names which contain special
+  characters such as a space, a tab, a comma, a double quote, etc.
+  See also: https://www.monetdb.org/bugzilla/show_bug.cgi?id=6183
+
 * Wed Dec 21 2016 Sjoerd Mullender <sjoerd@acm.org>
 - Compiled and released new jars: monetdb-jdbc-2.24.jar, monetdb-mcl-1.14.jar
   and updated jdbcclient.jar
--- a/SQLSTATEs
+++ b/SQLSTATEs
@@ -1,56 +1,71 @@
-08M01 opening logfile failed
+Following SQLStates are MonetDB JDBC driver specific:
 01M02 redirect warning
-M0M03 illegal arguments (invalid call of internal function)
 01M03 illegal arguments (invalid call of internal function)
-M0M04 only supported in SQL mode
-M1M05 invalid argument (user supplied)
-M0M06 savepoint is not MonetSavepoint
 01M07 unrecognised clientinfo property
 01M08 read-only conection mode not supported
 01M09 transaction mode not supported
-M0M10 protocol violation/unexpected server response
 01M10 unexpected server output
 01M11 server-client autocommit state mismatch
-M0M12 matching client handle referenced by server not found
 01M13 concurrency mode not supported
 01M14 scrolling mode not supported
 01M15 holdability mode not supported
-M1M16 multistatements not supported in batches
-M1M17 result set not expected for DML or DDL-statement
 01M18 generated keys for columns not supported
-M1M19 response is not a result set
-M1M20 object closed
 01M21 cursors not supported
-0AM21 cursors not supported
 01M22 JDBC escape syntax not supported
 01M23 field size limitation not supported
 01M24 query time out not supported
-M1M25 failed reading from/writing to object stream
+
+08M01 opening logfile failed
 08M26 invalid URI
-M0M27 unknown error
+08M33 connection timed out
+
+0AM21 cursors not supported
+0AM34 Java generics not supported
+
 22M28 invalid BLOB format
-M0M29 assert
+22M29 invalid inet format
+22M30 invalid url format
+22M31 invalid uuid format
+22M32 invalid json format
+
+2BM37 dependent objects still exist
+2DM30 autocommit mode active
 3BM30 autocommit mode active
-2DM30 autocommit mode active
+
 42M31 user/role already exists
 42M32 user/role not found
-08M33 connection timeout
-0AM34 Java generics not supported
 42M35 sequence not found
 42M36 cannot restart sequence with NULL
-2BM37 dependent objects still exist
+
+M0M03 illegal arguments (invalid call of internal function)
+M0M04 only supported in SQL mode
+M0M06 savepoint is not MonetSavepoint
+M0M10 protocol violation/unexpected server response
+M0M12 matching client handle referenced by server not found
+M0M27 unknown error
+M0M29 assert
+
+M1M05 invalid argument (user supplied)
+M1M16 multistatements not supported in batches
+M1M17 result set not expected for DML or DDL-statement
+M1M19 response is not a result set
+M1M20 object closed
+M1M25 failed reading from/writing to object stream
 
-TODO:
-JDBC 4.1 suggests the following SQLException subclass mapping:
-NonTransientSQLExeceptions (fails when same operation executed again)
-0A SQLFeatureNotSupportedException
-08 SQLNonTransientConnectionException
-22 SQLDataException
-23 SQLIntegrityConstraintViolationException
-28 SQLInvalidAuthorizationException
-42 SQLSyntaxErrorException
-TransientSQLExeceptions (retry of same operation might succeed)
-08 SQLTransientConnectionException
-40 SQLTransactionRollbackException
-   SQLTimeoutException
+SQLState codes are used in SQLExceptions.
+JDBC 4.1 defines the following SQLException subclass mappings:
+ NonTransientSQLExceptions (fails when same operation executed again)
+   0A SQLFeatureNotSupportedException
+   08 SQLNonTransientConnectionException
+   22 SQLDataException
+   23 SQLIntegrityConstraintViolationException
+   28 SQLInvalidAuthorizationSpecException
+   42 SQLSyntaxErrorException
+ TransientSQLExeceptions (retry of same operation might succeed)
+   08 SQLTransientConnectionException
+   40 SQLTransactionRollbackException
+   null SQLTimeoutException
 
+See also: http://docs.oracle.com/javase/7/docs/api/java/sql/SQLException.html
+See also: https://en.wikibooks.org/wiki/Structured_Query_Language/SQLSTATE
+
--- a/release.txt
+++ b/release.txt
@@ -1,6 +1,6 @@
 RELEASE NOTES
-MonetDB JDBC driver version 2.24 (Liberica/MCL-1.14)
-Release date: 2016-12-15
+MonetDB JDBC driver version 2.26 (Liberica/MCL-1.15)
+Release date: 2017-07-28
 
 This JDBC driver is designed for use with MonetDB, a main-memory
 database.  For more information see https://www.monetdb.org/.
@@ -55,8 +55,8 @@ Currently implemented JDBC 4.1 interface
     - setArray
     - setAsciiStream, setBinaryStream, setUnicodeStream
     - setBlob
-    - setNCharacterStream, setNClob, setNString
-    - setRef, setRowId, setSQLXML, setURL
+    - setNClob
+    - setRef, setRowId, setSQLXML
 
   * java.sql.ParameterMetaData
 
@@ -64,9 +64,9 @@ Currently implemented JDBC 4.1 interface
     The next features/methods are NOT implemented:
     - getArray
     - getAsciiStream, getUnicodeStream
-    - getNCharacterStream, getNClob, getNString
+    - getNClob
     - getRef, getRowId, getSQLXML
-    - all methods related to updateable result sets
+    - All methods related to updateable result sets
 
   * java.sql.ResultSetMetaData
 
@@ -83,10 +83,13 @@ Currently implemented JDBC 4.1 interface
     A simple implementation using a StringBuilder to store the whole CLOB
     The next features/methods are NOT implemented:
     - getAsciiStream
-    - getCharacterStream
     - setAsciiStream
     - setCharacterStream
 
+  * java.sql.SQLData
+    implemented by class: nl.cwi.monetdb.jdbc.types.INET
+            and by class: nl.cwi.monetdb.jdbc.types.URL
+
   * javax.sql.DataSource (not tested)
 
 
@@ -96,7 +99,6 @@ The next java.sql.* interfaces are NOT i
   * java.sql.NClob
   * java.sql.Ref
   * java.sql.Rowid
-  * java.sql.SQLData
   * java.sql.SQLInput
   * java.sql.SQLOutput
   * java.sql.SQLXML
--- a/src/main/java/nl/cwi/monetdb/client/JdbcClient.java
+++ b/src/main/java/nl/cwi/monetdb/client/JdbcClient.java
@@ -54,11 +54,11 @@ import java.util.zip.GZIPInputStream;
 public final class JdbcClient {
 
 	private static Connection con;
+	private static DatabaseMetaData dbmd;
 	private static Statement stmt;
 	private static BufferedReader in;
 	private static PrintWriter out;
 	private static Exporter exporter;
-	private static DatabaseMetaData dbmd;
 
 	public static void main(String[] args) throws Exception {
 		CmdLineOpts copts = new CmdLineOpts();
@@ -158,20 +158,21 @@ public final class JdbcClient {
 			System.exit(1);
 		}
 		// we can actually compare pointers (objects) here
-		if (!Objects.equals(user, copts.getOption("user").getArgument())) pass = null;
+		if (user != copts.getOption("user").getArgument())
+			pass = null;
 
 		if (copts.getOption("help").isPresent()) {
 			System.out.print(
 				"Usage java -jar jdbcclient.jar\n" +
-				"                  [-h host[:port]] [-p port] [-f file] [-u user]\n" +
-				"                  [-l language] [-d database] [-e] [-D [table]]\n" +
-				"                  [-X<opt>]\n" +
+				"\t\t[-h host[:port]] [-p port] [-f file] [-u user]\n" +
+				"\t\t[-l language] [-d database] [-e] [-D [table]]\n" +
+				"\t\t[-X<opt>]\n" +
 				"or using long option equivalents --host --port --file --user --language\n" +
 				"--dump --echo --database.\n" +
 				"Arguments may be written directly after the option like -p50000.\n" +
 				"\n" +
-				"If no host and port are given, localhost and 50000 are assumed.  An .monetdb\n" +
-				"file may exist in the user's home directory.  This file can contain\n" +
+				"If no host and port are given, localhost and 50000 are assumed.\n" +
+				"An .monetdb file may exist in the user's home directory.  This file can contain\n" +
 				"preferences to use each time JdbcClient is started.  Options given on the\n" +
 				"command line override the preferences file.  The .monetdb file syntax is\n" +
 				"<option>=<value> where option is one of the options host, port, file, mode\n" +
@@ -219,7 +220,8 @@ public final class JdbcClient {
 			host = host + ":" + copts.getOption("port").getArgument();
 		}
 
-		//Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");
+		// make sure the driver is loaded
+		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
 
 		// build the extra arguments of the JDBC connect string
 		String attr = "?";
@@ -227,12 +229,15 @@ public final class JdbcClient {
 		String lang = oc.getArgument();
 		if (oc.isPresent())
 			attr += "language=" + lang + "&";
+
+/* Xquery is no longer functional or supported
 		// set some behaviour based on the language XQuery
 		if (lang.equals("xquery")) {
 			scolonterm = false;	// no ; to end a statement
 			if (!copts.getOption("Xoutput").isPresent())
 				xmlMode = true; // the user will like xml results, most probably
 		}
+*/
 		oc = copts.getOption("Xdebug");
 		if (oc.isPresent()) {
 			attr += "debug=true&";
@@ -273,6 +278,7 @@ public final class JdbcClient {
 			// SQL language
 			dbmd = null;
 		}
+
 		stmt = con.createStatement();
 
 		// see if we will have to perform a database dump (only in SQL mode)
@@ -295,9 +301,9 @@ public final class JdbcClient {
 			List<Table> tables = new LinkedList<>();
 			while (tbl.next()) {
 				tables.add(new Table(
-					tbl.getString("TABLE_SCHEM"),
-					tbl.getString("TABLE_NAME"),
-					tbl.getString("TABLE_TYPE")));
+					tbl.getString(2),	// 2 = "TABLE_SCHEM"
+					tbl.getString(3),	// 3 = "TABLE_NAME"
+					tbl.getString(4)));	// 4 = "TABLE_TYPE"
 			}
 			tbl.close();
 
@@ -329,23 +335,21 @@ public final class JdbcClient {
 					}
 				}
 			} else {
-				/* this returns everything, so including SYSTEM TABLE
-				 * constraints */
+				/* this returns everything, so including SYSTEM TABLE constraints */
 				tbl = dbmd.getImportedKeys(null, null, null);
 				while (tbl.next()) {
-					// find FK table object
-					Table fk = Table.findTable(tbl.getString("FKTABLE_SCHEM") + "." + tbl.getString("FKTABLE_NAME"), tables);
+					// find FK table object  6 = "FKTABLE_SCHEM", 7 = "FKTABLE_NAME"
+					Table fk = Table.findTable(tbl.getString(6) + "." + tbl.getString(7), tables);
 
-					// find PK table object
-					Table pk = Table.findTable(tbl.getString("PKTABLE_SCHEM") + "." + tbl.getString("PKTABLE_NAME"), tables);
+					// find PK table object  2 = "PKTABLE_SCHEM", 3 = "PKTABLE_NAME"
+					Table pk = Table.findTable(tbl.getString(2) + "." + tbl.getString(3), tables);
 
-					// this happens when a system table has referential
-					// constraints
+					// this happens when a system table has referential constraints
 					if (fk == null || pk == null)
 						continue;
 
-					// add PK table dependancy to FK table
-					fk.addDependancy(pk);
+					// add PK table dependency to FK table
+					fk.addDependency(pk);
 				}
 				tbl.close();
 
@@ -473,8 +477,7 @@ public final class JdbcClient {
 	 *
 	 * @param uri URL or filename as String
 	 * @return a BufferedReader for the uri
-	 * @throws Exception if uri cannot be identified as a valid URL or
-	 *         file
+	 * @throws Exception if uri cannot be identified as a valid URL or file
 	 */
 	static BufferedReader getReader(String uri) throws Exception {
 		BufferedReader ret = null;
@@ -611,40 +614,54 @@ public final class JdbcClient {
 						out.println("\\q      quits this program");
 						out.println("\\h      this help screen");
 						if (dbmd != null)
-							out.println("\\d      list available tables and views");
+							out.println("\\d      list available tables and views in current schema");
 						out.println("\\d<obj> describes the given table or view");
 						out.println("\\l<uri> executes the contents of the given file or URL");
 						out.println("\\i<uri> batch executes the inserts from the given file or URL");
 					} else if (dbmd != null && command.startsWith("\\d")) {
+						ResultSet tbl = null;
 						try {
-							String object = command.substring(2).trim().toLowerCase();
+							String object = command.substring(2).trim();
 							if (scolonterm && object.endsWith(";"))
 								object = object.substring(0, object.length() - 1);
-							if (!object.isEmpty()) {
+							if (object.isEmpty()) {
+								// list available tables and views in current schema
+								String current_schema = con.getSchema();
+								tbl = dbmd.getTables(null, current_schema, null, null);
+
+								// give us a list of all non-system tables and views (including temp ones)
+								while (tbl.next()) {
+									String tableType = tbl.getString(4);	// 4 = "TABLE_TYPE"
+									if (tableType != null && !tableType.startsWith("SYSTEM "))
+										out.println(tableType + "\t" +
+											tbl.getString(2) + "." +	// 2 = "TABLE_SCHEM"
+											tbl.getString(3));	// 3 = "TABLE_NAME"
+								}
+								tbl.close();
+								tbl = null;
+							} else {
+								// describes the given table or view
 								String schema;
+								String obj_nm = object;
+								boolean found = false;
 								int dot = object.indexOf(".");
-								if (dot != -1) {
-									// use provided schema
+								if (dot > 0) {
+									// use specified schema
 									schema = object.substring(0, dot);
-									object = object.substring(dot + 1);
+									obj_nm = object.substring(dot + 1);
 								} else {
 									// use current schema
 									schema = con.getSchema();
 								}
-								ResultSet tbl = dbmd.getTables(null, schema, null, null);
-
-								// we have an object, see if we can find it
-								boolean found = false;
-								while (tbl.next()) {
-									String tableName = tbl.getString("TABLE_NAME");
-									String schemaName = tbl.getString("TABLE_SCHEM");
-									if ((dot == -1 && tableName.equalsIgnoreCase(object)) ||
-										(schemaName + "." + tableName).equalsIgnoreCase(object))
-									{
+								tbl = dbmd.getTables(null, schema, obj_nm, null);
+								while (tbl.next() && !found) {
+									String tableName = tbl.getString(3);	// 3 = "TABLE_NAME"
+									String schemaName = tbl.getString(2);	// 2 = "TABLE_SCHEM"
+									if (obj_nm.equals(tableName) && schema.equals(schemaName)) {
 										// we found it, describe it
 										exporter.dumpSchema(dbmd,
-												tbl.getString("TABLE_TYPE"),
-												tbl.getString("TABLE_CAT"),
+												tbl.getString(4),	// 4 = "TABLE_TYPE"
+												tbl.getString(1),	// 1 = "TABLE_CAT"
 												schemaName,
 												tableName);
 
@@ -653,22 +670,10 @@ public final class JdbcClient {
 									}
 								}
 								tbl.close();
+								tbl = null;
 
 								if (!found)
 									System.err.println("Unknown table or view: " + object);
-							} else {
-								String current_schema = con.getSchema();
-								ResultSet tbl = dbmd.getTables(null, current_schema, null, null);
-
-								// give us a list of all non-system tables and views (including temp ones)
-								while (tbl.next()) {
-									String tableType = tbl.getString("TABLE_TYPE");
-									if (tableType != null && !tableType.startsWith("SYSTEM "))
-										out.println(tableType + "\t" +
-											tbl.getString("TABLE_SCHEM") + "." +
-											tbl.getString("TABLE_NAME"));
-								}
-								tbl.close();
 							}
 						} catch (SQLException e) {
 							out.flush();
@@ -676,6 +681,9 @@ public final class JdbcClient {
 								System.err.println("Error [" + e.getSQLState() + "]: " + e.getMessage());
 								// print all error messages in the chain (if any)
 							} while ((e = e.getNextException()) != null);
+						} finally {
+							if (tbl != null)
+								tbl.close();
 						}
 					} else if (command.startsWith("\\l") || command.startsWith("\\i")) {
 						String object = command.substring(2).trim();
@@ -845,7 +853,7 @@ public final class JdbcClient {
 	 * is sent to the server as-is.
 	 *
 	 * @param batchSize the number of items to store in the batch before
-	 *                  sending them to the database for execution.
+	 *		sending them to the database for execution.
 	 * @throws IOException if an IO exception occurs.
 	 */
 	public static void processBatch(int batchSize) throws IOException {
@@ -1120,12 +1128,12 @@ class Table {
 		this.fqname = schem + "." + name;
 	}
 
-	void addDependancy(Table dependsOn) throws Exception {
+	void addDependency(Table dependsOn) throws Exception {
 		if (this.fqname.equals(dependsOn.fqname))
-			throw new Exception("Cyclic dependancy graphs are not supported (foreign key relation references self)");
+			throw new Exception("Cyclic dependency graphs are not supported (foreign key relation references self)");
 
 		if (dependsOn.needs.contains(this))
-			throw new Exception("Cyclic dependancy graphs are not supported (foreign key relation a->b and b->a)");
+			throw new Exception("Cyclic dependency graphs are not supported (foreign key relation a->b and b->a)");
 
 		if (!needs.contains(dependsOn))
 			needs.add(dependsOn);
@@ -1148,18 +1156,10 @@ class Table {
 		return schem;
 	}
 
-	String getSchemQ() {
-		return JdbcClient.dq(schem);
-	}
-
 	String getName() {
 		return name;
 	}
 
-	String getNameQ() {
-		return JdbcClient.dq(name);
-	}
-
 	String getType() {
 		return type;
 	}
@@ -1169,7 +1169,7 @@ class Table {
 	}
 
 	String getFqnameQ() {
-		return getSchemQ() + "." + getNameQ();
+		return JdbcClient.dq(schem) + "." + JdbcClient.dq(name);
 	}
 
 	public String toString() {
@@ -1190,7 +1190,7 @@ class Table {
 		for (int i = 0; i < table.needs.size(); i++) {
 			Table child = table.needs.get(i);
 			if (parents.contains(child))
-				throw new Exception("Cyclic dependancy graphs are not supported (cycle detected for " + child.fqname + ")");
+				throw new Exception("Cyclic dependency graphs are not supported (cycle detected for " + child.fqname + ")");
 			checkForLoop(child, parents);
 		}
 	}
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java
@@ -39,6 +39,24 @@ public class MonetBlob implements Blob, 
 		return buffer;
 	}
 
+	static MonetBlob create(String in) {
+		// unpack the HEX (BLOB) notation to real bytes
+		int len = in.length() / 2;
+		byte[] buf = new byte[len];
+		int offset;
+		for (int i = 0; i < len; i++) {
+			offset = 2 * i;
+			buf[i] = (byte)Integer.parseInt(in.substring(offset, offset + 2), 16);
+		}
+		return new MonetBlob(buf);
+	}
+
+	/* internal utility method */
+	private void checkBufIsNotNull() throws SQLException {
+		if (buffer == null)
+			throw new SQLException("This MonetBlob has been freed", "M1M20");
+	}
+
 	//== begin interface Blob
 
 	/**
@@ -61,8 +79,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public InputStream getBinaryStream() throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		return new ByteArrayInputStream(buffer);
 	}
 
@@ -79,8 +96,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public InputStream getBinaryStream(long pos, long length) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		if (pos < 1)
 			throw new SQLException("pos is less than 1", "M1M05");
 		if (pos - 1 > buffer.length)
@@ -103,10 +119,9 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public byte[] getBytes(long pos, int length) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		try {
-			return Arrays.copyOfRange(buffer, (int) pos - 1, (int) pos - 1 + length);
+			return java.util.Arrays.copyOfRange(buffer, (int) pos - 1, (int) pos - 1 + length);
 		} catch (IndexOutOfBoundsException e) {
 			throw new SQLException(e.getMessage(), "M0M10");
 		}
@@ -120,9 +135,8 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public long length() throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
-		return (long) buffer.length;
+		checkBufIsNotNull();
+		return (long)buffer.length;
 	}
 
 	/**
@@ -150,8 +164,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public long position(byte[] pattern, long start) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		try {
 			for (int i = (int)(start - 1); i < buffer.length - pattern.length; i++) {
 				int j;
@@ -184,12 +197,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public OutputStream setBinaryStream(long pos) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
-		if (pos < 1)
-			throw new SQLException("pos is less than 1", "M1M05");
-		throw new SQLFeatureNotSupportedException("Operation setBinaryStream(long pos) currently not supported",
-				"0A000");
+		throw new SQLFeatureNotSupportedException("Method setBinaryStream(long pos) not supported", "0A000");
 	}
 
 	/**
@@ -222,8 +230,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		try {
 			/* transactions? what are you talking about? */
 			System.arraycopy(bytes, offset - 1 + (int) pos, buffer, (int) pos, len - (int) pos);
@@ -241,8 +248,7 @@ public class MonetBlob implements Blob, 
 	 */
 	@Override
 	public void truncate(long len) throws SQLException {
-		if (buffer == null)
-			throw new SQLException("This Blob object has been freed", "M1M20");
+		checkBufIsNotNull();
 		if (buffer.length > len) {
 			byte[] newbuf = new byte[(int)len];
 			System.arraycopy(buffer, 0, newbuf, 0, (int) len);
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java
@@ -11,6 +11,7 @@ package nl.cwi.monetdb.jdbc;
 import java.io.*;
 import java.sql.Clob;
 import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 
 /**
  * The MonetClob class implements the {@link java.sql.Clob} interface.  Because
@@ -24,19 +25,28 @@ import java.sql.SQLException;
  * @author Fabian Groffen
  */
 public class MonetClob implements Clob, Serializable, Comparable<MonetClob> {
-	
+
 	private final StringBuilder buffer;
 
 	public MonetClob(String in) {
-		buffer = new StringBuilder(in);
+		if(in != null)
+			buffer = new StringBuilder(in);
+		else
+			buffer = null;
 	}
 
 	public MonetClob(char[] toParse, int startPosition, int count) {
 		buffer = new StringBuilder(new String(toParse, startPosition, count));
 	}
 
+	/* internal utility method */
+	private void checkBufIsNotNull() throws SQLException {
+		if (buffer == null)
+			throw new SQLException("This MonetClob has been freed", "M1M20");
+	}
+
 	//== begin interface Clob
-	
+
 	/**
 	 * This method frees the Clob object and releases the resources the resources that it holds. The object is invalid
 	 * once the free method is called.
@@ -46,7 +56,8 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public void free() {
-		buffer.setLength(0);
+		if (buffer != null)
+			buffer.setLength(0);
 	}
 
 	/**
@@ -57,6 +68,7 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public InputStream getAsciiStream() throws SQLException {
+		checkBufIsNotNull();
 		if (buffer.length() == 0)
 			throw new SQLException("This Clob has been freed", "M1M20");
 		return new ByteArrayInputStream(buffer.toString().getBytes());
@@ -71,9 +83,8 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public Reader getCharacterStream() throws SQLException {
-        if (buffer.length() == 0)
-            throw new SQLException("This Clob has been freed", "M1M20");
-        return new StringReader(buffer.toString());
+		checkBufIsNotNull();
+		return new StringReader(buffer.toString());
 	}
 
 	/**
@@ -88,9 +99,8 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public Reader getCharacterStream(long pos, long length) throws SQLException {
-        if (buffer.length() == 0)
-            throw new SQLException("This Clob has been freed", "M1M20");
-        return new StringReader(buffer.substring((int)(pos - 1), (int)(pos - 1 + length)));
+		checkBufIsNotNull();
+		return new StringReader(getSubString(pos, (int)length));
 	}
 
 	/**
@@ -104,8 +114,7 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public String getSubString(long pos, int length) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
+		checkBufIsNotNull();
 		try {
 			return buffer.substring((int)(pos - 1), (int)(pos - 1 + length));
 		} catch (IndexOutOfBoundsException e) {
@@ -121,9 +130,8 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public long length() throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
-		return (long) buffer.length();
+		checkBufIsNotNull();
+		return (long)buffer.length();
 	}
 
 	/**
@@ -137,6 +145,7 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public long position(Clob searchstr, long start) throws SQLException {
+		checkBufIsNotNull();
 		return position(searchstr.getSubString(1L, (int)(searchstr.length())), start);
 	}
 
@@ -151,23 +160,18 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public long position(String searchstr, long start) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
+		checkBufIsNotNull();
 		return (long)(buffer.indexOf(searchstr, (int)(start - 1)));
 	}
 
 	@Override
 	public OutputStream setAsciiStream(long pos) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
-		throw new SQLException("Operation setAsciiStream(long pos) currently not supported", "0A000");
+		throw new SQLFeatureNotSupportedException("Method setAsciiStream(long pos) not supported", "0A000");
 	}
 
 	@Override
 	public Writer setCharacterStream(long pos) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
-		throw new SQLException("Operation setCharacterStream(long pos) currently not supported", "0A000");
+		throw new SQLFeatureNotSupportedException("Method setCharacterStream(long pos) not supported", "0A000");
 	}
 
 	/**
@@ -195,12 +199,9 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public int setString(long pos, String str, int offset, int len) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
-
+		checkBufIsNotNull();
 		int buflen = buffer.length();
 		int retlen = Math.min(buflen, (int)(pos - 1 + len));
-		
 		if (retlen > 0) {
 			buffer.replace((int)(pos - 1), (int)(pos + retlen), str.substring(offset - 1, (offset + len)));
 			return retlen;
@@ -217,8 +218,7 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public void truncate(long len) throws SQLException {
-		if (buffer.length() == 0)
-			throw new SQLException("This Clob has been freed", "M1M20");
+		checkBufIsNotNull();
 		buffer.setLength((int) len);
 	}
 
@@ -230,8 +230,8 @@ public class MonetClob implements Clob, 
 	 */
 	@Override
 	public String toString() {
-		if (buffer.length() == 0)
-			return "<a freed MonetClob instance>";
+		if (buffer == null || buffer.length() == 0)
+			return "null";
 		return buffer.toString();
 	}
 
@@ -247,7 +247,11 @@ public class MonetClob implements Clob, 
 	 * Overriding the hashCode method for the byte array.
 	 */
 	@Override
-	public int hashCode() { return this.buffer.toString().hashCode(); }
+	public int hashCode() {
+		if (buffer == null || buffer.length() == 0)
+			return 0;
+		return this.buffer.toString().hashCode();
+	}
 
 	/**
 	 * Adding the compare to method.
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -11,6 +11,7 @@ import nl.cwi.monetdb.mcl.protocol.Start
 import nl.cwi.monetdb.mcl.responses.*;
 
 import java.io.IOException;
+import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.sql.*;
 import java.util.*;
@@ -41,1654 +42,1769 @@ import java.util.concurrent.Executor;
  * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira
  * @version 1.3
  */
-public abstract class MonetConnection extends MonetWrapper implements Connection {
+public abstract class MonetConnection extends MonetWrapper implements Connection, AutoCloseable {
 
-    /** The sequence counter */
-    private static int SeqCounter = 0;
+	/** The sequence counter */
+	private static int SeqCounter = 0;
 
-    /**
-     * Gets the current sequence counter.
-     *
-     * @return The current sequence counter
-     */
-    public static int getSeqCounter() {
-        return SeqCounter;
-    }
+	/**
+	 * Gets the current sequence counter.
+	 *
+	 * @return The current sequence counter
+	 */
+	public static int getSeqCounter() {
+		return SeqCounter;
+	}
 
-    /** The successful processed input properties */
-    protected final Properties conn_props;
-    /** The language to connect with */
-    protected IMonetDBLanguage language;
-    /** Authentication hash method */
-    protected final String hash;
-    /** An optional thread that is used for sending large queries */
-    private SenderThread senderThread;
-    /** Whether this Connection is closed (and cannot be used anymore) */
-    private boolean closed;
-    /** Whether this Connection is in autocommit mode */
-    private boolean autoCommit = true;
-    /** The stack of warnings for this Connection object */
-    private SQLWarning warnings;
-    /** The Connection specific mapping of user defined types to Java types */
-    private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() {
-        private static final long serialVersionUID = 1L; {
-            put("inet", MonetINET.class);
-            put("url", MonetURL.class);
-        }
-    };
+	/** The successful processed input properties */
+	protected final Properties conn_props;
+	/** The language to connect with */
+	protected IMonetDBLanguage language;
+	/** Authentication hash method */
+	protected final String hash;
+	/** An optional thread that is used for sending large queries */
+	private SenderThread senderThread;
+	/** Whether this Connection is closed (and cannot be used anymore) */
+	private boolean closed;
+	/** Whether this Connection is in autocommit mode */
+	private boolean autoCommit = true;
+	/** The stack of warnings for this Connection object */
+	private SQLWarning warnings;
+	/** The Connection specific mapping of user defined types to Java types */
+	private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>() {
+		private static final long serialVersionUID = 1L; {
+			put("inet", MonetINET.class);
+			put("url", MonetURL.class);
+		}
+	};
+
+	// See javadoc for documentation about WeakHashMap if you don't know what it does !!!NOW!!!
+	// (only when you deal with it of course)
+	/** A Map containing all (active) Statements created from this Connection */
+	private Map<Statement,?> statements = new WeakHashMap<>();
+	/** The number of results we receive from the server at once */
+	private int curReplySize = -1; // the server by default uses -1 (all)
+	/** Whether or not BLOB is mapped to LONGVARBINARY within the driver */
+	private final boolean blobIsBinary;
+	/** Whether or not CLOB is mapped to LONGVARCHAR within the driver */
+	private final boolean clobIsLongChar;
+	/** The underlying proticol provided by the connection (MAPI or embedded) */
+	protected AbstractProtocol protocol;
+	/** Tells if the connection is embedded or not */
+	private final boolean isEmbedded;
 
-    // See javadoc for documentation about WeakHashMap if you don't know what it does !!!NOW!!!
-    // (only when you deal with it of course)
-    /** A Map containing all (active) Statements created from this Connection */
-    private Map<Statement,?> statements = new WeakHashMap<>();
-    /** The number of results we receive from the server at once */
-    private int curReplySize = -1; // the server by default uses -1 (all)
-    /** Whether or not BLOB is mapped to LONGVARBINARY within the driver */
-    private final boolean blobIsBinary;
-    /** Whether or not CLOB is mapped to LONGVARCHAR within the driver */
-    private final boolean clobIsLongChar;
-    /** The underlying proticol provided by the connection (MAPI or embedded) */
-    protected AbstractProtocol protocol;
-    /** Tells if the connection is embedded or not */
-    private final boolean isEmbedded;
+	/**
+	 * Constructor of a Connection for MonetDB. At this moment the current implementation limits itself to storing the
+	 * given host, database, username and password for later use by the createStatement() call.  This constructor is
+	 * only accessible to classes from the jdbc package.
+	 */
+	public MonetConnection(Properties props, String hash, IMonetDBLanguage language, boolean blobIsBinary,
+						   boolean clobIsLongChar) {
+		this.conn_props = props;
+		this.hash = hash;
+		this.language = language;
+		this.blobIsBinary = blobIsBinary;
+		this.clobIsLongChar = clobIsLongChar;
+		//"instance of" should be cleanner, but this is faster.
+		this.isEmbedded = props.getProperty("embedded", "false").equals("true");
+	}
+
+	/**
+	 * Checks if the conection is embedded or not
+	 *
+	 * @return If the connection is embedded
+	 */
+	public boolean isEmbedded() {
+		return isEmbedded;
+	}
 
-    /**
-     * Constructor of a Connection for MonetDB. At this moment the current implementation limits itself to storing the
-     * given host, database, username and password for later use by the createStatement() call.  This constructor is
-     * only accessible to classes from the jdbc package.
-     *
-     * @throws IOException if an error occurs
-     */
-    public MonetConnection(Properties props, String hash, IMonetDBLanguage language, boolean blobIsBinary,
-                           boolean clobIsLongChar) throws IOException {
-        this.conn_props = props;
-        this.hash = hash;
-        this.language = language;
-        this.blobIsBinary = blobIsBinary;
-        this.clobIsLongChar = clobIsLongChar;
-        //"instance of" should be cleanner, but this is faster.
-        this.isEmbedded = props.getProperty("embedded", "false").equals("true");
-    }
+	/**
+	 * Gets the connection's language data.
+	 *
+	 * @return The connection's language data
+	 */
+	public IMonetDBLanguage getLanguage() {
+		return language;
+	}
 
-    /**
-     * Checks if the conection is embedded or not
-     *
-     * @return If the connection is embedded
-     */
-    public boolean isEmbedded() {
-        return isEmbedded;
-    }
+	/**
+	 * Gets the connection's protocol.
+	 *
+	 * @return The connection's protocol
+	 */
+	public AbstractProtocol getProtocol() {
+		return this.protocol;
+	}
 
-    /**
-     * Gets the connection's language data.
-     *
-     * @return The connection's language data
-     */
-    public IMonetDBLanguage getLanguage() {
-        return language;
-    }
-
-    /**
-     * Gets the connection's protocol.
-     *
-     * @return The connection's protocol
-     */
-    public AbstractProtocol getProtocol() {
-        return this.protocol;
-    }
+	/**
+	 * Connects to the server, authenticating the user.
+	 *
+	 * @param user The user name to authenticate
+	 * @param pass The user's password
+	 * @return A List with informational (warning) messages. If this list is empty; then there are no warnings.
+	 * @throws IOException if an I/O error occurs when creating the socket
+	 * @throws ProtocolException if bogus data is received
+	 * @throws MCLException if an MCL related error occurs
+	 */
+	public abstract List<String> connect(String user, String pass) throws IOException, ProtocolException, MCLException;
 
-    /**
-     * Connects to the server, authenticating the user.
-     *
-     * @param user The user name to authenticate
-     * @param pass The user's password
-     * @return A List with informational (warning) messages. If this list is empty; then there are no warnings.
-     * @throws IOException if an I/O error occurs when creating the socket
-     * @throws ProtocolException if bogus data is received
-     * @throws MCLException if an MCL related error occurs
-     */
-    public abstract List<String> connect(String user, String pass) throws IOException, ProtocolException, MCLException;
+	/**
+	 * Gets the underlying connection block size length.
+	 *
+	 * @return The block size length
+	 */
+	public abstract int getBlockSize();
 
-    /**
-     * Gets the underlying connection block size length.
-     *
-     * @return The block size length
-     */
-    public abstract int getBlockSize();
+	/**
+	 * Gets the underlying connection default fetch size for DataBlock responses.
+	 *
+	 * @return The default fetch size
+	 */
+	public abstract int getDefFetchsize();
+
+	/**
+	 * Gets the initial value for the StringBuilder size.
+	 *
+	 * @return The initial value for the StringBuilder size
+	 */
+	public abstract int initialStringBuilderSize();
 
-    /**
-     * Gets the underlying connection default fetch size for DataBlock responses.
-     *
-     * @return The default fetch size
-     */
-    public abstract int getDefFetchsize();
+	/**
+	 * Gets the underlying connection socket timeout.
+	 *
+	 * @return The underlying connection socket timeout
+	 */
+	public abstract int getSoTimeout() throws SocketException;
 
-    /**
-     * Gets the initial value for the StringBuilder size.
-     *
-     * @return The initial value for the StringBuilder size
-     */
-    public abstract int initialStringBuilderSize();
+	/**
+	 * Sets the underlying connection socket timeout.
+	 *
+	 * @param timeout The specified timeout, in milliseconds. A timeout of zero is interpreted as an infinite timeout
+	 */
+	public abstract void setSoTimeout(int timeout) throws SocketException;
 
-    /**
-     * Gets the underlying connection socket timeout.
-     *
-     * @return The underlying connection socket timeout
-     */
-    public abstract int getSoTimeout();
+	/**
+	 * Closes the underlying connection implementation.
+	 *
+	 * @throws IOException if an I/O error occurs while closing the connection
+	 */
+	public abstract void closeUnderlyingConnection() throws IOException;
 
-    /**
-     * Sets the underlying connection socket timeout.
-     *
-     * @param timeout The specified timeout, in milliseconds. A timeout of zero is interpreted as an infinite timeout
-     */
-    public abstract void setSoTimeout(int timeout);
+	/**
+	 * Gets the underlying connection JDBC String URL.
+	 *
+	 * @return The underlying connection JDBC String URL
+	 */
+	public abstract String getJDBCURL();
 
-    /**
-     * Closes the underlying connection implementation.
-     *
-     * @throws IOException if an I/O error occurs while closing the connection
-     */
-    public abstract void closeUnderlyingConnection() throws IOException;
-
-    /**
-     * Gets the underlying connection JDBC String URL.
-     *
-     * @return The underlying connection JDBC String URL
-     */
-    public abstract String getJDBCURL();
-
-    /**
-     * Sends a control command to the server.
-     *
-     * @param commandID the command identifier according to {@link ControlCommands} listing
-     * @param data The integer to send according to the control command
-     * @throws SQLException if an IO exception or a database error occurs
-     */
-    public abstract void sendControlCommand(int commandID, int data) throws SQLException;
+	/**
+	 * Sends a control command to the server.
+	 *
+	 * @param commandID the command identifier according to {@link ControlCommands} listing
+	 * @param data The integer to send according to the control command
+	 * @throws SQLException if an IO exception or a database error occurs
+	 */
+	public abstract void sendControlCommand(int commandID, int data) throws SQLException;
 
-    /**
-     * Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be
-     * automatically released. All Statements created from this Connection will be closed when this method is called.
-     *
-     * Calling the method close on a Connection object that is already closed is a no-op.
-     */
-    @Override
-    public void close() {
-        for (Statement st : statements.keySet()) {
-            try {
-                st.close();
-            } catch (SQLException e) {
-                // better luck next time!
-            }
-        }
-        // close the socket or the embedded server
-        try {
-            this.closeUnderlyingConnection();
-        } catch (IOException e) {
-            // ignore it
-        }
-        // close active SendThread if any
-        if (senderThread != null) {
-            senderThread.shutdown();
-            senderThread = null;
-        }
-        // report ourselves as closed
-        closed = true;
-    }
+	/**
+	 * Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be
+	 * automatically released. All Statements created from this Connection will be closed when this method is called.
+	 *
+	 * Calling the method close on a Connection object that is already closed is a no-op.
+	 */
+	@Override
+	public void close() {
+		for (Statement st : statements.keySet()) {
+			try {
+				st.close();
+			} catch (SQLException e) {
+				// better luck next time!
+			}
+		}
+		// close the socket or the embedded server
+		try {
+			this.closeUnderlyingConnection();
+		} catch (IOException e) {
+			// ignore it
+		}
+		// close active SendThread if any
+		if (senderThread != null) {
+			senderThread.shutdown();
+			senderThread = null;
+		}
+		// report ourselves as closed
+		closed = true;
+	}
+
+	/**
+	 * Destructor called by garbage collector before destroying this object tries to disconnect the MonetDB connection
+	 * if it has not been disconnected already.
+	 */
+	@Override
+	protected void finalize() throws Throwable {
+		this.close();
+		super.finalize();
+	}
+
+	//== methods of interface Connection
+
+	/**
+	 * Clears all warnings reported for this Connection object. After a call to this method, the method getWarnings
+	 * returns null until a new warning is reported for this Connection object.
+	 */
+	@Override
+	public void clearWarnings() {
+		warnings = null;
+	}
 
-    /**
-     * Destructor called by garbage collector before destroying this object tries to disconnect the MonetDB connection
-     * if it has not been disconnected already.
-     */
-    @Override
-    protected void finalize() throws Throwable {
-        this.close();
-        super.finalize();
-    }
-
-    //== methods of interface Connection
+	/**
+	 * Makes all changes made since the previous commit/rollback permanent and releases any database locks currently
+	 * held by this Connection object. This method should be used only when auto-commit mode has been disabled.
+	 *
+	 * @throws SQLException if a database access error occurs or this Connection object is in auto-commit mode
+	 * @see #setAutoCommit(boolean)
+	 */
+	@Override
+	public void commit() throws SQLException {
+		// note: can't use sendIndependentCommand here because we need to process the auto_commit state the server gives
+		this.sendTransactionCommand("COMMIT");
+	}
 
-    /**
-     * Clears all warnings reported for this Connection object. After a call to this method, the method getWarnings
-     * returns null until a new warning is reported for this Connection object.
-     */
-    @Override
-    public void clearWarnings() {
-        warnings = null;
-    }
+	/**
+	 * Creates a Statement object for sending SQL statements to the
+	 * database.  SQL statements without parameters are normally
+	 * executed using Statement objects. If the same SQL statement is
+	 * executed many times, it may be more efficient to use a
+	 * PreparedStatement object.
+	 *
+	 * Result sets created using the returned Statement object will by
+	 * default be type TYPE_FORWARD_ONLY and have a concurrency level of
+	 * CONCUR_READ_ONLY.
+	 *
+	 * @return a new default Statement object
+	 * @throws SQLException if a database access error occurs
+	 */
+	@Override
+	public Statement createStatement() throws SQLException {
+		return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+	}
 
-    private void createResponseList(String query) throws SQLException {
-        // create a container for the result
-        ResponseList l = new ResponseList(0, 0, ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);
-        // send commit to the server
-        try {
-            l.processQuery(query);
-        } finally {
-            l.close();
-        }
-    }
+	/**
+	 * Creates a Statement object that will generate ResultSet objects
+	 * with the given type and concurrency. This method is the same as
+	 * the createStatement method above, but it allows the default
+	 * result set type and concurrency to be overridden.
+	 *
+	 * @param resultSetType a result set type; one of
+	 *        ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
+	 *        or ResultSet.TYPE_SCROLL_SENSITIVE
+	 * @param resultSetConcurrency a concurrency type; one of
+	 *        ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
+	 * @return a new Statement object that will generate ResultSet objects with
+	 *         the given type and concurrency
+	 * @throws SQLException if a database access error occurs
+	 */
+	@Override
+	public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+		return createStatement(resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+	}
 
-    /**
-     * Makes all changes made since the previous commit/rollback permanent and releases any database locks currently
-     * held by this Connection object. This method should be used only when auto-commit mode has been disabled.
-     *
-     * @throws SQLException if a database access error occurs or this Connection object is in auto-commit mode
-     * @see #setAutoCommit(boolean)
-     */
-    @Override
-    public void commit() throws SQLException {
-        // note: can't use sendIndependentCommand here because we need to process the auto_commit state the server gives
-        this.createResponseList("COMMIT");
-    }
+	/**
+	 * Creates a Statement object that will generate ResultSet objects
+	 * with the given type, concurrency, and holdability.  This method
+	 * is the same as the createStatement method above, but it allows
+	 * the default result set type, concurrency, and holdability to be
+	 * overridden.
+	 *
+	 * @param resultSetType one of the following ResultSet constants:
+	 * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
+	 * or ResultSet.TYPE_SCROLL_SENSITIVE
+	 * @param resultSetConcurrency one of the following ResultSet
+	 * constants: ResultSet.CONCUR_READ_ONLY or
+	 * ResultSet.CONCUR_UPDATABLE
+	 * @param resultSetHoldability one of the following ResultSet
+	 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
+	 * ResultSet.CLOSE_CURSORS_AT_COMMIT
+	 *
+	 * @return a new Statement      object that will generate ResultSet
+	 * objects with the given type, concurrency, and holdability
+	 * @throws SQLException if a database access error occurs or the
+	 * given parameters are not ResultSet constants indicating type,
+	 * concurrency, and holdability
+	 */
+	@Override
+	public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+		try {
+			Statement ret = new MonetStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
+			// store it in the map for when we close...
+			statements.put(ret, null);
+			return ret;
+		} catch (IllegalArgumentException e) {
+			throw new SQLException(e.toString(), "M0M03");
+		}
+		// we don't have to catch SQLException because that is declared to
+		// be thrown
+	}
 
-    /**
-     * Creates a Statement object for sending SQL statements to the database. SQL statements without parameters are
-     * normally executed using Statement objects. If the same SQL statement is executed many times, it may be more
-     * efficient to use a PreparedStatement object.
-     *
-     * Result sets created using the returned Statement object will by default be type TYPE_FORWARD_ONLY and have a
-     * concurrency level of CONCUR_READ_ONLY.
-     *
-     * @return a new default Statement object
-     * @throws SQLException if a database access error occurs
-     */
-    @Override
-    public Statement createStatement() throws SQLException {
-        return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
-                ResultSet.HOLD_CURSORS_OVER_COMMIT);
-    }
+	/**
+	 * Retrieves the current auto-commit mode for this Connection object.
+	 *
+	 * @return the current state of this Connection object's auto-commit mode
+	 * @see #setAutoCommit(boolean)
+	 */
+	@Override
+	public boolean getAutoCommit() throws SQLException {
+		return autoCommit;
+	}
 
-    /**
-     * Creates a Statement object that will generate ResultSet objects with the given type and concurrency. This method
-     * is the same as the createStatement method above, but it allows the default result set type and concurrency to be
-     * overridden.
-     *
-     * @param resultSetType a result set type; one of ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
-     * or ResultSet.TYPE_SCROLL_SENSITIVE
-     * @param resultSetConcurrency a concurrency type; one of ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
-     * @return a new Statement object that will generate ResultSet objects with the given type and concurrency
-     * @throws SQLException if a database access error occurs
-     */
-    @Override
-    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
-        return createStatement(resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
-    }
+	/**
+	 * Retrieves this Connection object's current catalog name.
+	 *
+	 * @return the current catalog name or null if there is none
+	 * @throws SQLException if a database access error occurs or the current language is not SQL
+	 */
+	@Override
+	public String getCatalog() throws SQLException {
+		// MonetDB does NOT support catalogs
+		return null;
+	}
 
-    /**
-     * Creates a Statement object that will generate ResultSet objects
-     * with the given type, concurrency, and holdability.  This method
-     * is the same as the createStatement method above, but it allows
-     * the default result set type, concurrency, and holdability to be
-     * overridden.
-     *
-     * @param resultSetType one of the following ResultSet constants:
-     * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
-     * or ResultSet.TYPE_SCROLL_SENSITIVE
-     * @param resultSetConcurrency one of the following ResultSet
-     * constants: ResultSet.CONCUR_READ_ONLY or
-     * ResultSet.CONCUR_UPDATABLE
-     * @param resultSetHoldability one of the following ResultSet
-     * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
-     * ResultSet.CLOSE_CURSORS_AT_COMMIT
-     *
-     * @return a new Statement      object that will generate ResultSet
-     * objects with the given type, concurrency, and holdability
-     * @throws SQLException if a database access error occurs or the
-     * given parameters are not ResultSet constants indicating type,
-     * concurrency, and holdability
-     */
-    @Override
-    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
-            throws SQLException {
-        try {
-            Statement ret = new MonetStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
-            // store it in the map for when we close...
-            statements.put(ret, null);
-            return ret;
-        } catch (IllegalArgumentException e) {
-            throw new SQLException(e.toString(), "M0M03");
-        }
-        // we don't have to catch SQLException because that is declared to
-        // be thrown
-    }
+	/**
+	 * Retrieves the current holdability of ResultSet objects created using this Connection object.
+	 *
+	 * @return the holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
+	 */
+	@Override
+	public int getHoldability() {
+		// TODO: perhaps it is better to have the server implement
+		//       CLOSE_CURSORS_AT_COMMIT
+		return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+	}
 
-    /**
-     * Retrieves the current auto-commit mode for this Connection object.
-     *
-     * @return the current state of this Connection object's auto-commit mode
-     * @see #setAutoCommit(boolean)
-     */
-    @Override
-    public boolean getAutoCommit() throws SQLException {
-        return autoCommit;
-    }
+	/**
+	 * Retrieves a DatabaseMetaData object that contains metadata about
+	 * the database to which this Connection object represents a
+	 * connection. The metadata includes information about the
+	 * database's tables, its supported SQL grammar, its stored
+	 * procedures, the capabilities of this connection, and so on.
+	 *
+	 * @throws SQLException if the current language is not SQL
+	 * @return a DatabaseMetaData object for this Connection object
+	 */
+	@Override
+	public DatabaseMetaData getMetaData() throws SQLException {
+		if (!this.language.getRepresentation().equals("sql")) {
+			throw new SQLException("This method is only supported in SQL mode", "M0M04");
+		}
+		return new MonetDatabaseMetaData(this);
+	}
 
-    /**
-     * Retrieves this Connection object's current catalog name.
-     *
-     * @return the current catalog name or null if there is none
-     * @throws SQLException if a database access error occurs or the current language is not SQL
-     */
-    @Override
-    public String getCatalog() throws SQLException {
-        // MonetDB does NOT support catalogs
-        return null;
-    }
+	/**
+	 * Retrieves this Connection object's current transaction isolation level.
+	 *
+	 * @return the current transaction isolation level, which will be Connection.TRANSACTION_SERIALIZABLE
+	 */
+	@Override
+	public int getTransactionIsolation() {
+		return TRANSACTION_SERIALIZABLE;
+	}
+
+	/**
+	 * Retrieves the Map object associated with this Connection object. Unless the application has added an entry,
+	 * the type map returned will be empty.
+	 *
+	 * @return the java.util.Map object associated with this Connection object
+	 */
+	@Override
+	public Map<String,Class<?>> getTypeMap() {
+		return typeMap;
+	}
 
-    /**
-     * Retrieves the current holdability of ResultSet objects created using this Connection object.
-     *
-     * @return the holdability, one of ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT
-     */
-    @Override
-    public int getHoldability() {
-        // TODO: perhaps it is better to have the server implement
-        //       CLOSE_CURSORS_AT_COMMIT
-        return ResultSet.HOLD_CURSORS_OVER_COMMIT;
-    }
-
-    /**
-     * Retrieves a DatabaseMetaData object that contains metadata about
-     * the database to which this Connection object represents a
-     * connection. The metadata includes information about the
-     * database's tables, its supported SQL grammar, its stored
-     * procedures, the capabilities of this connection, and so on.
-     *
-     * @throws SQLException if the current language is not SQL
-     * @return a DatabaseMetaData object for this Connection object
-     */
-    @Override
-    public DatabaseMetaData getMetaData() throws SQLException {
-        if (!this.language.getRepresentation().equals("sql")) {
-            throw new SQLException("This method is only supported in SQL mode", "M0M04");
-        }
-        return new MonetDatabaseMetaData(this);
-    }
+	/**
+	 * Retrieves the first warning reported by calls on this Connection
+	 * object.  If there is more than one warning, subsequent warnings
+	 * will be chained to the first one and can be retrieved by calling
+	 * the method SQLWarning.getNextWarning on the warning that was
+	 * retrieved previously.
+	 *
+	 * This method may not be called on a closed connection; doing so will cause an SQLException to be thrown.
+	 *
+	 * Note: Subsequent warnings will be chained to this SQLWarning.
+	 *
+	 * @return the first SQLWarning object or null if there are none
+	 * @throws SQLException if a database access error occurs or this method is called on a closed connection
+	 */
+	@Override
+	public SQLWarning getWarnings() throws SQLException {
+		if (closed) {
+			throw new SQLException("Cannot call on closed Connection", "M1M20");
+		}
+		// if there are no warnings, this will be null, which fits with the specification.
+		return warnings;
+	}
 
-    /**
-     * Retrieves this Connection object's current transaction isolation level.
-     *
-     * @return the current transaction isolation level, which will be Connection.TRANSACTION_SERIALIZABLE
-     */
-    @Override
-    public int getTransactionIsolation() {
-        return TRANSACTION_SERIALIZABLE;
-    }
-
-    /**
-     * Retrieves the Map object associated with this Connection object. Unless the application has added an entry,
-     * the type map returned will be empty.
-     *
-     * @return the java.util.Map object associated with this Connection object
-     */
-    @Override
-    public Map<String,Class<?>> getTypeMap() {
-        return typeMap;
-    }
+	/**
+	 * Retrieves whether this Connection object has been closed.  A
+	 * connection is closed if the method close has been called on it or
+	 * if certain fatal errors have occurred.  This method is guaranteed
+	 * to return true only when it is called after the method
+	 * Connection.close has been called.
+	 *
+	 * This method generally cannot be called to determine whether a
+	 * connection to a database is valid or invalid.  A typical client
+	 * can determine that a connection is invalid by catching any
+	 * exceptions that might be thrown when an operation is attempted.
+	 *
+	 * @return true if this Connection object is closed; false if it is still open
+	 */
+	@Override
+	public boolean isClosed() {
+		return closed;
+	}
 
-    /**
-     * Retrieves the first warning reported by calls on this Connection
-     * object.  If there is more than one warning, subsequent warnings
-     * will be chained to the first one and can be retrieved by calling
-     * the method SQLWarning.getNextWarning on the warning that was
-     * retrieved previously.
-     *
-     * This method may not be called on a closed connection; doing so will cause an SQLException to be thrown.
-     *
-     * Note: Subsequent warnings will be chained to this SQLWarning.
-     *
-     * @return the first SQLWarning object or null if there are none
-     * @throws SQLException if a database access error occurs or this method is called on a closed connection
-     */
-    @Override
-    public SQLWarning getWarnings() throws SQLException {
-        if (closed) {
-            throw new SQLException("Cannot call on closed Connection", "M1M20");
-        }
-        // if there are no warnings, this will be null, which fits with the specification.
-        return warnings;
-    }
+	/**
+	 * Retrieves whether this Connection object is in read-only mode.
+	 * MonetDB currently doesn't support updateable result sets, but
+	 * updates are possible.  Hence the Connection object is never in
+	 * read-only mode.
+	 *
+	 * @return true if this Connection object is read-only; false otherwise
+	 */
+	@Override
+	public boolean isReadOnly() {
+		return false;
+	}
+
+	@Override
+	public String nativeSQL(String sql) {
+		/* there is currently no way to get the native MonetDB rewritten SQL string back, so just return the original string */
+		/* in future we may replace/remove the escape sequences { <escape-type> ...} before sending it to the server */
+		return sql;
+	}
 
-    /**
-     * Retrieves whether this Connection object has been closed.  A
-     * connection is closed if the method close has been called on it or
-     * if certain fatal errors have occurred.  This method is guaranteed
-     * to return true only when it is called after the method
-     * Connection.close has been called.
-     *
-     * This method generally cannot be called to determine whether a
-     * connection to a database is valid or invalid.  A typical client
-     * can determine that a connection is invalid by catching any
-     * exceptions that might be thrown when an operation is attempted.
-     *
-     * @return true if this Connection object is closed; false if it is still open
-     */
-    @Override
-    public boolean isClosed() {
-        return closed;
-    }
+	@Override
+	public CallableStatement prepareCall(String sql) {
+		/* not implemented yet */
+		return null;
+	}
 
-    /**
-     * Retrieves whether this Connection object is in read-only mode.
-     * MonetDB currently doesn't support updateable result sets, but
-     * updates are possible.  Hence the Connection object is never in
-     * read-only mode.
-     *
-     * @return true if this Connection object is read-only; false otherwise
-     */
-    @Override
-    public boolean isReadOnly() {
-        return false;
-    }
+	@Override
+	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {
+		/* not implemented yet */
+		return null;
+	}
 
-    @Override
-    public String nativeSQL(String sql) {return sql;}
-
-    @Override
-    public CallableStatement prepareCall(String sql) {return null;}
+	@Override
+	public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) {
+		/* not implemented yet */
+		return null;
+	}
 
-    @Override
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) {return null;}
-
-    @Override
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
-                                         int resultSetHoldability) {return null;}
+	/**
+	 * Creates a PreparedStatement object for sending parameterized SQL
+	 * statements to the database.
+	 *
+	 * A SQL statement with or without IN parameters can be pre-compiled
+	 * and stored in a PreparedStatement object. This object can then be
+	 * used to efficiently execute this statement multiple times.
+	 *
+	 * Note: This method is optimized for handling parametric SQL
+	 * statements that benefit from precompilation. If the driver
+	 * supports precompilation, the method prepareStatement will send
+	 * the statement to the database for precompilation. Some drivers
+	 * may not support precompilation. In this case, the statement may
+	 * not be sent to the database until the PreparedStatement object is
+	 * executed. This has no direct effect on users; however, it does
+	 * affect which methods throw certain SQLException objects.
+	 *
+	 * Result sets created using the returned PreparedStatement object
+	 * will by default be type TYPE_FORWARD_ONLY and have a concurrency
+	 * level of CONCUR_READ_ONLY.
+	 *
+	 * @param sql an SQL statement that may contain one or more '?' IN
+	 *        parameter placeholders
+	 * @return a new default PreparedStatement object containing the
+	 *         pre-compiled SQL statement
+	 * @throws SQLException if a database access error occurs
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql) throws SQLException {
+		return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+	}
 
-    /**
-     * Creates a PreparedStatement object for sending parameterized SQL
-     * statements to the database.
-     *
-     * A SQL statement with or without IN parameters can be pre-compiled
-     * and stored in a PreparedStatement object. This object can then be
-     * used to efficiently execute this statement multiple times.
-     *
-     * Note: This method is optimized for handling parametric SQL
-     * statements that benefit from precompilation. If the driver
-     * supports precompilation, the method prepareStatement will send
-     * the statement to the database for precompilation. Some drivers
-     * may not support precompilation. In this case, the statement may
-     * not be sent to the database until the PreparedStatement object is
-     * executed. This has no direct effect on users; however, it does
-     * affect which methods throw certain SQLException objects.
-     *
-     * Result sets created using the returned PreparedStatement object
-     * will by default be type TYPE_FORWARD_ONLY and have a concurrency
-     * level of CONCUR_READ_ONLY.
-     *
-     * @param sql an SQL statement that may contain one or more '?' IN
-     *        parameter placeholders
-     * @return a new default PreparedStatement object containing the
-     *         pre-compiled SQL statement
-     * @throws SQLException if a database access error occurs
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-        return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
-                ResultSet.HOLD_CURSORS_OVER_COMMIT);
-    }
+	/**
+	 * Creates a PreparedStatement object that will generate ResultSet
+	 * objects with the given type and concurrency.  This method is the
+	 * same as the prepareStatement method above, but it allows the
+	 * default result set type and concurrency to be overridden.
+	 *
+	 * @param sql a String object that is the SQL statement to be sent to the
+	 *        database; may contain one or more ? IN parameters
+	 * @param resultSetType a result set type; one of
+	 *        ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
+	 *        or ResultSet.TYPE_SCROLL_SENSITIVE
+	 * @param resultSetConcurrency a concurrency type; one of
+	 *        ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
+	 * @return a new PreparedStatement object containing the pre-compiled SQL
+	 *         statement that will produce ResultSet objects with the given
+	 *         type and concurrency
+	 * @throws SQLException if a database access error occurs or the given
+	 *         parameters are not ResultSet constants indicating
+	 *         type and concurrency
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+		return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
+	}
 
-    /**
-     * Creates a PreparedStatement object that will generate ResultSet
-     * objects with the given type and concurrency.  This method is the
-     * same as the prepareStatement method above, but it allows the
-     * default result set type and concurrency to be overridden.
-     *
-     * @param sql a String object that is the SQL statement to be sent to the
-     *            database; may contain one or more ? IN parameters
-     * @param resultSetType a result set type; one of
-     *        ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
-     *        or ResultSet.TYPE_SCROLL_SENSITIVE
-     * @param resultSetConcurrency a concurrency type; one of
-     *        ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
-     * @return a new PreparedStatement object containing the pre-compiled SQL
-     *         statement that will produce ResultSet objects with the given
-     *         type and concurrency
-     * @throws SQLException if a database access error occurs or the given
-     *                      parameters are not ResultSet constants indicating
-     *                      type and concurrency
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
-            throws SQLException {
-        return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
-    }
+	/**
+	 * Creates a PreparedStatement object that will generate ResultSet
+	 * objects with the given type, concurrency, and holdability.
+	 *
+	 * This method is the same as the prepareStatement method above, but
+	 * it allows the default result set type, concurrency, and
+	 * holdability to be overridden.
+	 *
+	 * @param sql a String object that is the SQL statement to be sent
+	 * to the database; may contain one or more ? IN parameters
+	 * @param resultSetType one of the following ResultSet constants:
+	 * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
+	 * or ResultSet.TYPE_SCROLL_SENSITIVE
+	 * @param resultSetConcurrency one of the following ResultSet
+	 * constants: ResultSet.CONCUR_READ_ONLY or
+	 * ResultSet.CONCUR_UPDATABLE
+	 * @param resultSetHoldability one of the following ResultSet
+	 * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
+	 * ResultSet.CLOSE_CURSORS_AT_COMMIT
+	 * @return a new PreparedStatement object, containing the
+	 * pre-compiled SQL statement, that will generate ResultSet objects
+	 * with the given type, concurrency, and holdability
+	 * @throws SQLException if a database access error occurs or the
+	 * given parameters are not ResultSet constants indicating type,
+	 * concurrency, and holdability
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+			throws SQLException {
+		try {
+			PreparedStatement ret = new MonetPreparedStatement(this, resultSetType, resultSetConcurrency,
+					resultSetHoldability, sql);
+			// store it in the map for when we close...
+			statements.put(ret, null);
+			return ret;
+		} catch (IllegalArgumentException e) {
+			throw new SQLException(e.toString(), "M0M03");
+		}
+		// we don't have to catch SQLException because that is declared to
+		// be thrown
+	}
 
-    /**
-     * Creates a PreparedStatement object that will generate ResultSet
-     * objects with the given type, concurrency, and holdability.
-     *
-     * This method is the same as the prepareStatement method above, but
-     * it allows the default result set type, concurrency, and
-     * holdability to be overridden.
-     *
-     * @param sql a String object that is the SQL statement to be sent
-     * to the database; may contain one or more ? IN parameters
-     * @param resultSetType one of the following ResultSet constants:
-     * ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE,
-     * or ResultSet.TYPE_SCROLL_SENSITIVE
-     * @param resultSetConcurrency one of the following ResultSet
-     * constants: ResultSet.CONCUR_READ_ONLY or
-     * ResultSet.CONCUR_UPDATABLE
-     * @param resultSetHoldability one of the following ResultSet
-     * constants: ResultSet.HOLD_CURSORS_OVER_COMMIT or
-     * ResultSet.CLOSE_CURSORS_AT_COMMIT
-     * @return a new PreparedStatement object, containing the
-     * pre-compiled SQL statement, that will generate ResultSet objects
-     * with the given type, concurrency, and holdability
-     * @throws SQLException if a database access error occurs or the
-     * given parameters are not ResultSet constants indicating type,
-     * concurrency, and holdability
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
-                                              int resultSetHoldability) throws SQLException {
-        try {
-            PreparedStatement ret = new MonetPreparedStatement(this, resultSetType, resultSetConcurrency,
-                    resultSetHoldability, sql);
-            // store it in the map for when we close...
-            statements.put(ret, null);
-            return ret;
-        } catch (IllegalArgumentException e) {
-            throw new SQLException(e.toString(), "M0M03");
-        }
-        // we don't have to catch SQLException because that is declared to
-        // be thrown
-    }
+	/**
+	 * Creates a default PreparedStatement object that has the
+	 * capability to retrieve auto-generated keys.  The given constant
+	 * tells the driver whether it should make auto-generated keys
+	 * available for retrieval.  This parameter is ignored if the SQL
+	 * statement is not an INSERT statement.
+	 *
+	 * Note: This method is optimized for handling parametric SQL
+	 * statements that benefit from precompilation.  If the driver
+	 * supports precompilation, the method prepareStatement will send
+	 * the statement to the database for precompilation. Some drivers
+	 * may not support precompilation.  In this case, the statement may
+	 * not be sent to the database until the PreparedStatement object is
+	 * executed.  This has no direct effect on users; however, it does
+	 * affect which methods throw certain SQLExceptions.
+	 *
+	 * Result sets created using the returned PreparedStatement object
+	 * will by default be type TYPE_FORWARD_ONLY and have a concurrency
+	 * level of CONCUR_READ_ONLY.
+	 *
+	 * @param sql an SQL statement that may contain one or more '?' IN
+	 *        parameter placeholders
+	 * @param autoGeneratedKeys a flag indicating whether auto-generated
+	 *        keys should be returned; one of
+	 *        Statement.RETURN_GENERATED_KEYS or
+	 *        Statement.NO_GENERATED_KEYS
+	 * @return a new PreparedStatement object, containing the
+	 *         pre-compiled SQL statement, that will have the capability
+	 *         of returning auto-generated keys
+	 * @throws SQLException - if a database access error occurs or the
+	 *         given parameter is not a Statement  constant indicating
+	 *         whether auto-generated keys should be returned
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+		if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS &&
+				autoGeneratedKeys != Statement.NO_GENERATED_KEYS)
+			throw new SQLException("Invalid argument, expected RETURN_GENERATED_KEYS or NO_GENERATED_KEYS", "M1M05");
 
-    /**
-     * Creates a default PreparedStatement object that has the
-     * capability to retrieve auto-generated keys.  The given constant
-     * tells the driver whether it should make auto-generated keys
-     * available for retrieval.  This parameter is ignored if the SQL
-     * statement is not an INSERT statement.
-     *
-     * Note: This method is optimized for handling parametric SQL
-     * statements that benefit from precompilation.  If the driver
-     * supports precompilation, the method prepareStatement will send
-     * the statement to the database for precompilation. Some drivers
-     * may not support precompilation.  In this case, the statement may
-     * not be sent to the database until the PreparedStatement object is
-     * executed.  This has no direct effect on users; however, it does
-     * affect which methods throw certain SQLExceptions.
-     *
-     * Result sets created using the returned PreparedStatement object
-     * will by default be type TYPE_FORWARD_ONLY and have a concurrency
-     * level of CONCUR_READ_ONLY.
-     *
-     * @param sql an SQL statement that may contain one or more '?' IN
-     *        parameter placeholders
-     * @param autoGeneratedKeys a flag indicating whether auto-generated
-     *        keys should be returned; one of
-     *        Statement.RETURN_GENERATED_KEYS or
-     *        Statement.NO_GENERATED_KEYS
-     * @return a new PreparedStatement object, containing the
-     *         pre-compiled SQL statement, that will have the capability
-     *         of returning auto-generated keys
-     * @throws SQLException - if a database access error occurs or the
-     *         given parameter is not a Statement  constant indicating
-     *         whether auto-generated keys should be returned
-     */
-    @Override
-    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS && autoGeneratedKeys != Statement.NO_GENERATED_KEYS) {
-            throw new SQLException("Invalid argument, expected RETURN_GENERATED_KEYS or NO_GENERATED_KEYS", "M1M05");
-        }
-		/* MonetDB has no way to disable this, so just do the normal thing ;) */
-        return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
-    }
+		/* MonetDB has no way to disable this, so just do the normal
+		 * thing ;) */
+		return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+	}
 
-    @Override
-    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) {return null;}
-
-    @Override
-    public PreparedStatement prepareStatement(String sql, String[] columnNames) {return null;}
+	/**
+	 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
+	 * This array contains the indexes of the columns in the target table that contain the auto-generated keys that should be made available.
+	 * The driver will ignore the array if the SQL statement is not an INSERT statement, or an SQL statement able to
+	 * return auto-generated keys (the list of such statements is vendor-specific).
+	 *
+	 * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object.
+	 * This object can then be used to efficiently execute this statement multiple times.
+	 *
+	 * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation.
+	 * If the driver supports precompilation, the method prepareStatement will send the statement to the database for precompilation.
+	 * Some drivers may not support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement
+	 * object is executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions.
+	 *
+	 * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have
+	 * a concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling getHoldability().
+	 *
+	 * Parameters:
+	 *     sql - an SQL statement that may contain one or more '?' IN parameter placeholders
+	 *     columnIndexes - an array of column indexes indicating the columns that should be returned from the inserted row or rows
+	 * Returns:
+	 *     a new PreparedStatement object, containing the pre-compiled statement, that is capable of
+	 *     returning the auto-generated keys designated by the given array of column indexes
+	 * Throws:
+	 *     SQLException - if a database access error occurs or this method is called on a closed connection
+	 *     SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+		throw new SQLFeatureNotSupportedException("prepareStatement(String sql, int[] columnIndexes) not supported", "0A000");
+	}
 
-    /**
-     * Removes the given Savepoint object from the current transaction.
-     * Any reference to the savepoint after it have been removed will
-     * cause an SQLException to be thrown.
-     *
-     * @param savepoint the Savepoint object to be removed
-     * @throws SQLException if a database access error occurs or the given
-     *         Savepoint object is not a valid savepoint in the current
-     *         transaction
-     */
-    @Override
-    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-        if (!(savepoint instanceof MonetSavepoint)) {
-            throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
-        }
-        MonetSavepoint sp = (MonetSavepoint) savepoint;
-        // note: can't use sendIndependentCommand here because we need
-        // to process the auto_commit state the server gives
-        // create a container for the result
-        this.createResponseList("RELEASE SAVEPOINT " + sp.getName());
-    }
-
-    /**
-     * Undoes all changes made in the current transaction and releases
-     * any database locks currently held by this Connection object. This
-     * method should be used only when auto-commit mode has been
-     * disabled.
-     *
-     * @throws SQLException if a database access error occurs or this
-     *         Connection object is in auto-commit mode
-     * @see #setAutoCommit(boolean)
-     */
-    @Override
-    public void rollback() throws SQLException {
-        // note: can't use sendIndependentCommand here because we need
-        // to process the auto_commit state the server gives
-        // create a container for the result
-        this.createResponseList("ROLLBACK");
-    }
+	/**
+	 * Creates a default PreparedStatement object capable of returning the auto-generated keys designated by the given array.
+	 * This array contains the names of the columns in the target table that contain the auto-generated keys that should be returned.
+	 * The driver will ignore the array if the SQL statement is not an INSERT statement, or an SQL statement able to
+	 * return auto-generated keys (the list of such statements is vendor-specific).
+	 *
+	 * An SQL statement with or without IN parameters can be pre-compiled and stored in a PreparedStatement object.
+	 * This object can then be used to efficiently execute this statement multiple times.
+	 *
+	 * Note: This method is optimized for handling parametric SQL statements that benefit from precompilation.
+	 * If the driver supports precompilation, the method prepareStatement will send the statement to the database for precompilation.
+	 * Some drivers may not support precompilation. In this case, the statement may not be sent to the database until the PreparedStatement
+	 * object is executed. This has no direct effect on users; however, it does affect which methods throw certain SQLExceptions.
+	 *
+	 * Result sets created using the returned PreparedStatement object will by default be type TYPE_FORWARD_ONLY and have
+	 * a concurrency level of CONCUR_READ_ONLY. The holdability of the created result sets can be determined by calling getHoldability().
+	 *
+	 * Parameters:
+	 *     sql - an SQL statement that may contain one or more '?' IN parameter placeholders
+	 *     columnNames - an array of column names indicating the columns that should be returned from the inserted row or rows
+	 * Returns:
+	 *     a new PreparedStatement object, containing the pre-compiled statement, that is capable of
+	 *     returning the auto-generated keys designated by the given array of column names
+	 * Throws:
+	 *     SQLException - if a database access error occurs or this method is called on a closed connection
+	 *     SQLFeatureNotSupportedException - if the JDBC driver does not support this method
+	 */
+	@Override
+	public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+		throw new SQLFeatureNotSupportedException("prepareStatement(String sql, String[] columnNames) not supported", "0A000");
+	}
 
-    /**
-     * Undoes all changes made after the given Savepoint object was set.
-     *
-     * This method should be used only when auto-commit has been
-     * disabled.
-     *
-     * @param savepoint the Savepoint object to roll back to
-     * @throws SQLException if a database access error occurs, the
-     *         Savepoint object is no longer valid, or this Connection
-     *         object is currently in auto-commit mode
-     */
-    @Override
-    public void rollback(Savepoint savepoint) throws SQLException {
-        if (!(savepoint instanceof MonetSavepoint)) {
-            throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
-        }
-
-        MonetSavepoint sp = (MonetSavepoint)savepoint;
-        // note: can't use sendIndependentCommand here because we need
-        // to process the auto_commit state the server gives
-        // create a container for the result
-        this.createResponseList("ROLLBACK TO SAVEPOINT " + sp.getName());
-    }
+	/**
+	 * Removes the given Savepoint object from the current transaction.
+	 * Any reference to the savepoint after it have been removed will
+	 * cause an SQLException to be thrown.
+	 *
+	 * @param savepoint the Savepoint object to be removed
+	 * @throws SQLException if a database access error occurs or the given
+	 *         Savepoint object is not a valid savepoint in the current
+	 *         transaction
+	 */
+	@Override
+	public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+		if (!(savepoint instanceof MonetSavepoint)) {
+			throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
+		}
+		MonetSavepoint sp = (MonetSavepoint) savepoint;
+		// note: can't use sendIndependentCommand here because we need
+		// to process the auto_commit state the server gives
+		this.sendTransactionCommand("RELEASE SAVEPOINT " + sp.getName());
+	}
 
-    /**
-     * Sets this connection's auto-commit mode to the given state. If a
-     * connection is in auto-commit mode, then all its SQL statements
-     * will be executed and committed as individual transactions.
-     * Otherwise, its SQL statements are grouped into transactions that
-     * are terminated by a call to either the method commit or the
-     * method rollback. By default, new connections are in auto-commit
-     * mode.
-     *
-     * The commit occurs when the statement completes or the next
-     * execute occurs, whichever comes first. In the case of statements
-     * returning a ResultSet object, the statement completes when the
-     * last row of the ResultSet object has been retrieved or the
-     * ResultSet object has been closed. In advanced cases, a single
-     * statement may return multiple results as well as output parameter
-     * values. In these cases, the commit occurs when all results and
-     * output parameter values have been retrieved.
-     *
-     * NOTE: If this method is called during a transaction, the
-     * transaction is committed.
-     *
-     * @param autoCommit true to enable auto-commit mode; false to disable it
-     * @throws SQLException if a database access error occurs
-     * @see #getAutoCommit()
-     */
-    @Override
-    public void setAutoCommit(boolean autoCommit) throws SQLException {
-        if (this.autoCommit != autoCommit) {
-            this.sendControlCommand(ControlCommands.AUTO_COMMIT, (autoCommit ? 1 : 0));
-            this.autoCommit = autoCommit;
-        }
-    }
+	/**
+	 * Undoes all changes made in the current transaction and releases
+	 * any database locks currently held by this Connection object. This
+	 * method should be used only when auto-commit mode has been
+	 * disabled.
+	 *
+	 * @throws SQLException if a database access error occurs or this
+	 *         Connection object is in auto-commit mode
+	 * @see #setAutoCommit(boolean)
+	 */
+	@Override
+	public void rollback() throws SQLException {
+		// note: can't use sendIndependentCommand here because we need
+		// to process the auto_commit state the server gives
+		// create a container for the result
+		this.sendTransactionCommand("ROLLBACK");
+	}
 
-    /**
-     * Sets the given catalog name in order to select a subspace of this
-     * Connection object's database in which to work.  If the driver
-     * does not support catalogs, it will silently ignore this request.
-     */
-    @Override
-    public void setCatalog(String catalog) throws SQLException {
-        throw new SQLFeatureNotSupportedException("setCatalog(String catalog) not supported", "0A000");
-    }
+	/**
+	 * Undoes all changes made after the given Savepoint object was set.
+	 *
+	 * This method should be used only when auto-commit has been
+	 * disabled.
+	 *
+	 * @param savepoint the Savepoint object to roll back to
+	 * @throws SQLException if a database access error occurs, the
+	 *         Savepoint object is no longer valid, or this Connection
+	 *         object is currently in auto-commit mode
+	 */
+	@Override
+	public void rollback(Savepoint savepoint) throws SQLException {
+		if (!(savepoint instanceof MonetSavepoint)) {
+			throw new SQLException("This driver can only handle savepoints it created itself", "M0M06");
+		}
+
+		MonetSavepoint sp = (MonetSavepoint)savepoint;
+		// note: can't use sendIndependentCommand here because we need
+		// to process the auto_commit state the server gives
+		// create a container for the result
+		this.sendTransactionCommand("ROLLBACK TO SAVEPOINT " + sp.getName());
+	}
 
-    /**
-     * Changes the default holdability of ResultSet objects created using this
-     * Connection object to the given holdability. The default holdability of
-     * ResultSet objects can be be determined by invoking DatabaseMetaData.getResultSetHoldability().
-     *
-     * @param holdability - a ResultSet holdability constant; one of
-     *	ResultSet.HOLD_CURSORS_OVER_COMMIT or
-     *	ResultSet.CLOSE_CURSORS_AT_COMMIT
-     * @see #getHoldability()
-     */
-    @Override
-    public void setHoldability(int holdability) throws SQLException {
-        // we only support ResultSet.HOLD_CURSORS_OVER_COMMIT
-        if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
-            throw new SQLFeatureNotSupportedException("setHoldability(CLOSE_CURSORS_AT_COMMIT) not supported", "0A000");
-    }
+	/**
+	 * Sets this connection's auto-commit mode to the given state. If a
+	 * connection is in auto-commit mode, then all its SQL statements
+	 * will be executed and committed as individual transactions.
+	 * Otherwise, its SQL statements are grouped into transactions that
+	 * are terminated by a call to either the method commit or the
+	 * method rollback. By default, new connections are in auto-commit
+	 * mode.
+	 *
+	 * The commit occurs when the statement completes or the next
+	 * execute occurs, whichever comes first. In the case of statements
+	 * returning a ResultSet object, the statement completes when the
+	 * last row of the ResultSet object has been retrieved or the
+	 * ResultSet object has been closed. In advanced cases, a single
+	 * statement may return multiple results as well as output parameter
+	 * values. In these cases, the commit occurs when all results and
+	 * output parameter values have been retrieved.
+	 *
+	 * NOTE: If this method is called during a transaction, the
+	 * transaction is committed.
+	 *
+	 * @param autoCommit true to enable auto-commit mode; false to disable it
+	 * @throws SQLException if a database access error occurs
+	 * @see #getAutoCommit()
+	 */
+	@Override
+	public void setAutoCommit(boolean autoCommit) throws SQLException {
+		if (this.autoCommit != autoCommit) {
+			this.sendControlCommand(ControlCommands.AUTO_COMMIT, (autoCommit ? 1 : 0));
+			this.autoCommit = autoCommit;
+		}
+	}
 
-    /**
-     * Puts this connection in read-only mode as a hint to the driver to
-     * enable database optimizations.  MonetDB doesn't support any mode
-     * here, hence an SQLWarning is generated if attempted to set
-     * to true here.
-     *
-     * @param readOnly true enables read-only mode; false disables it
-     * @throws SQLException if a database access error occurs or this
-     *         method is called during a transaction.
-     */
-    @Override
-    public void setReadOnly(boolean readOnly) throws SQLException {
-        if (readOnly) {
-            addWarning("cannot setReadOnly(true): read-only Connection mode not supported", "01M08");
-        }
-    }
+	/**
+	 * Sets the given catalog name in order to select a subspace of this
+	 * Connection object's database in which to work.  If the driver
+	 * does not support catalogs, it will silently ignore this request.
+	 */
+	@Override
+	public void setCatalog(String catalog) throws SQLException {
+		throw new SQLFeatureNotSupportedException("setCatalog(String catalog) not supported", "0A000");
+	}
 
-    /**
-     * Creates an unnamed savepoint in the current transaction and
-     * returns the new Savepoint object that represents it.
-     *
-     * @return the new Savepoint object
-     * @throws SQLException if a database access error occurs or this Connection
-     *         object is currently in auto-commit mode
-     */
-    @Override
-    public Savepoint setSavepoint() throws SQLException {
-        // create a new Savepoint object
-        MonetSavepoint sp = new MonetSavepoint();
-        // note: can't use sendIndependentCommand here because we need
-        // to process the auto_commit state the server gives
-        // create a container for the result
-        this.createResponseList("SAVEPOINT " + sp.getName());
-        return sp;
-    }
+	/**
+	 * Changes the default holdability of ResultSet objects created using this
+	 * Connection object to the given holdability. The default holdability of
+	 * ResultSet objects can be be determined by invoking DatabaseMetaData.getResultSetHoldability().
+	 *
+	 * @param holdability - a ResultSet holdability constant; one of
+	 *	ResultSet.HOLD_CURSORS_OVER_COMMIT or
+	 *	ResultSet.CLOSE_CURSORS_AT_COMMIT
+	 * @see #getHoldability()
+	 */
+	@Override
+	public void setHoldability(int holdability) throws SQLException {
+		// we only support ResultSet.HOLD_CURSORS_OVER_COMMIT
+		if (holdability != ResultSet.HOLD_CURSORS_OVER_COMMIT)
+			throw new SQLFeatureNotSupportedException("setHoldability(CLOSE_CURSORS_AT_COMMIT) not supported", "0A000");
+	}
 
-    /**
-     * Creates a savepoint with the given name in the current
-     * transaction and returns the new Savepoint object that represents
-     * it.
-     *
-     * @param name a String containing the name of the savepoint
-     * @return the new Savepoint object
-     * @throws SQLException if a database access error occurs or this Connection
-     *         object is currently in auto-commit mode
-     */
-    @Override
-    public Savepoint setSavepoint(String name) throws SQLException {
-        // create a new Savepoint object
-        MonetSavepoint sp;
-        try {
-            sp = new MonetSavepoint(name);
-        } catch (IllegalArgumentException e) {
-            throw new SQLException(e.getMessage(), "M0M03");
-        }
-        // note: can't use sendIndependentCommand here because we need
-        // to process the auto_commit state the server gives
-        // create a container for the result
-        this.createResponseList("SAVEPOINT " + sp.getName());
-        return sp;
-    }
+	/**
+	 * Puts this connection in read-only mode as a hint to the driver to
+	 * enable database optimizations.  MonetDB doesn't support any mode
+	 * here, hence an SQLWarning is generated if attempted to set
+	 * to true here.
+	 *
+	 * @param readOnly true enables read-only mode; false disables it
+	 * @throws SQLException if a database access error occurs or this
+	 *         method is called during a transaction.
+	 */
+	@Override
+	public void setReadOnly(boolean readOnly) throws SQLException {
+		if (readOnly) {
+			addWarning("cannot setReadOnly(true): read-only Connection mode not supported", "01M08");
+		}
+	}
+
+	/**
+	 * Creates an unnamed savepoint in the current transaction and
+	 * returns the new Savepoint object that represents it.
+	 *
+	 * @return the new Savepoint object
+	 * @throws SQLException if a database access error occurs or this Connection
+	 *         object is currently in auto-commit mode
+	 */
+	@Override
+	public Savepoint setSavepoint() throws SQLException {
+		// create a new Savepoint object
+		MonetSavepoint sp = new MonetSavepoint();
+		// note: can't use sendIndependentCommand here because we need
+		// to process the auto_commit state the server gives
+		// create a container for the result
+		this.sendTransactionCommand("SAVEPOINT " + sp.getName());
+		return sp;
+	}
 
-    /**
-     * Attempts to change the transaction isolation level for this
-     * Connection object to the one given.  The constants defined in the
-     * interface Connection are the possible transaction isolation
-     * levels.
-     *
-     * @param level one of the following Connection constants: Connection.TRANSACTION_READ_UNCOMMITTED,
-     *        Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_REPEATABLE_READ, or
-     *        Connection.TRANSACTION_SERIALIZABLE.
-     */
-    @Override
-    public void setTransactionIsolation(int level) {
-        if (level != TRANSACTION_SERIALIZABLE) {
-            addWarning("MonetDB only supports fully serializable " +
-                    "transactions, continuing with transaction level raised to TRANSACTION_SERIALIZABLE", "01M09");
-        }
-    }
+	/**
+	 * Creates a savepoint with the given name in the current
+	 * transaction and returns the new Savepoint object that represents
+	 * it.
+	 *
+	 * @param name a String containing the name of the savepoint
+	 * @return the new Savepoint object
+	 * @throws SQLException if a database access error occurs or this Connection
+	 *         object is currently in auto-commit mode
+	 */
+	@Override
+	public Savepoint setSavepoint(String name) throws SQLException {
+		// create a new Savepoint object
+		MonetSavepoint sp;
+		try {
+			sp = new MonetSavepoint(name);
+		} catch (IllegalArgumentException e) {
+			throw new SQLException(e.getMessage(), "M0M03");
+		}
+		// note: can't use sendIndependentCommand here because we need
+		// to process the auto_commit state the server gives
+		// create a container for the result
+		this.sendTransactionCommand("SAVEPOINT " + sp.getName());
+		return sp;
+	}
 
-    /**
-     * Installs the given TypeMap object as the type map for this
-     * Connection object. The type map will be used for the custom
-     * mapping of SQL structured types and distinct types.
-     *
-     * @param map the java.util.Map object to install as the replacement for
-     *        this Connection  object's default type map
-     */
-    @Override
-    public void setTypeMap(Map<String, Class<?>> map) {
-        typeMap = map;
-    }
+	/**
+	 * Attempts to change the transaction isolation level for this
+	 * Connection object to the one given.  The constants defined in the
+	 * interface Connection are the possible transaction isolation
+	 * levels.
+	 *
+	 * @param level one of the following Connection constants: Connection.TRANSACTION_READ_UNCOMMITTED,
+	 *        Connection.TRANSACTION_READ_COMMITTED, Connection.TRANSACTION_REPEATABLE_READ, or
+	 *        Connection.TRANSACTION_SERIALIZABLE.
+	 */
+	@Override
+	public void setTransactionIsolation(int level) {
+		if (level != TRANSACTION_SERIALIZABLE) {
+			addWarning("MonetDB only supports fully serializable " +
+					"transactions, continuing with transaction level raised to TRANSACTION_SERIALIZABLE", "01M09");
+		}
+	}
+
+	/**
+	 * Installs the given TypeMap object as the type map for this
+	 * Connection object. The type map will be used for the custom
+	 * mapping of SQL structured types and distinct types.
+	 *
+	 * @param map the java.util.Map object to install as the replacement for
+	 *        this Connection  object's default type map
+	 */
+	@Override
+	public void setTypeMap(Map<String, Class<?>> map) {
+		typeMap = map;
+	}
 
-    /**
-     * Returns a string identifying this Connection to the MonetDB server.
-     *
-     * @return a String representing this Object
-     */
-    @Override
-    public String toString() {
-        return "MonetDB Connection (" + this.getJDBCURL() + ") " + (closed ? "disconnected" : "connected");
-    }
-
-    //== Java 1.6 methods (JDBC 4.0)
+	/**
+	 * Returns a string identifying this Connection to the MonetDB server.
+	 *
+	 * @return a String representing this Object
+	 */
+	@Override
+	public String toString() {
+		return "MonetDB Connection (" + this.getJDBCURL() + ") " + (closed ? "disconnected" : "connected");
+	}
 
-    /**
-     * Factory method for creating Array objects.
-     *
-     * Note: When createArrayOf is used to create an array object that
-     * maps to a primitive data type, then it is implementation-defined
-     * whether the Array object is an array of that primitive data type
-     * or an array of Object.
-     *
-     * Note: The JDBC driver is responsible for mapping the elements
-     * Object array to the default JDBC SQL type defined in
-     * java.sql.Types for the given class of Object. The default mapping
-     * is specified in Appendix B of the JDBC specification. If the
-     * resulting JDBC type is not the appropriate type for the given
-     * typeName then it is implementation defined whether an
-     * SQLException is thrown or the driver supports the resulting conversion.
-     *
-     * @param typeName the SQL name of the type the elements of the
-     *        array map to. The typeName is a database-specific name
-     *        which may be the name of a built-in type, a user-defined
-     *        type or a standard SQL type supported by this database.
-     *        This is the value returned by Array.getBaseTypeName
-     * @return an Array object whose elements map to the specified SQL type
-     * @throws SQLException if a database error occurs, the JDBC type
-     *         is not appropriate for the typeName and the conversion is
-     *         not supported, the typeName is null or this method is
-     *         called on a closed connection
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support this data type
-     * @since 1.6
-     */
-    @Override
-    public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        throw new SQLFeatureNotSupportedException("createArrayOf() not supported", "0A000");
-    }
+	/**
+	 * Factory method for creating Array objects.
+	 *
+	 * Note: When createArrayOf is used to create an array object that
+	 * maps to a primitive data type, then it is implementation-defined
+	 * whether the Array object is an array of that primitive data type
+	 * or an array of Object.
+	 *
+	 * Note: The JDBC driver is responsible for mapping the elements
+	 * Object array to the default JDBC SQL type defined in
+	 * java.sql.Types for the given class of Object. The default mapping
+	 * is specified in Appendix B of the JDBC specification. If the
+	 * resulting JDBC type is not the appropriate type for the given
+	 * typeName then it is implementation defined whether an
+	 * SQLException is thrown or the driver supports the resulting conversion.
+	 *
+	 * @param typeName the SQL name of the type the elements of the
+	 *        array map to. The typeName is a database-specific name
+	 *        which may be the name of a built-in type, a user-defined
+	 *        type or a standard SQL type supported by this database.
+	 *        This is the value returned by Array.getBaseTypeName
+	 * @return an Array object whose elements map to the specified SQL type
+	 * @throws SQLException if a database error occurs, the JDBC type
+	 *         is not appropriate for the typeName and the conversion is
+	 *         not supported, the typeName is null or this method is
+	 *         called on a closed connection
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support this data type
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+		throw new SQLFeatureNotSupportedException("createArrayOf() not supported", "0A000");
+	}
+
+
+	//== end methods of interface java.sql.Connection
 
-    /**
-     * Constructs an object that implements the Clob interface. The
-     * object returned initially contains no data. The setAsciiStream,
-     * setCharacterStream and setString methods of the Clob interface
-     * may be used to add data to the Clob.
-     *
-     * @return a MonetClob instance
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support MonetClob objects that can be filled in
-     * @since 1.6
-     */
-    @Override
-    public java.sql.Clob createClob() throws SQLException {
-        return new MonetClob("");
-    }
+	/**
+	 * Constructs an object that implements the Clob interface. The
+	 * object returned initially contains no data. The setAsciiStream,
+	 * setCharacterStream and setString methods of the Clob interface
+	 * may be used to add data to the Clob.
+	 *
+	 * @return a MonetClob instance
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support MonetClob objects that can be filled in
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.Clob createClob() throws SQLException {
+		return new MonetClob("");
+	}
 
-    /**
-     * Constructs an object that implements the Blob interface. The
-     * object returned initially contains no data. The setBinaryStream
-     * and setBytes methods of the Blob interface may be used to add
-     * data to the Blob.
-     *
-     * @return a MonetBlob instance
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support MonetBlob objects that can be filled in
-     * @since 1.6
-     */
-    @Override
-    public java.sql.Blob createBlob() throws SQLException {
-        return new MonetBlob(new byte[1]);
-    }
+	/**
+	 * Constructs an object that implements the Blob interface. The
+	 * object returned initially contains no data. The setBinaryStream
+	 * and setBytes methods of the Blob interface may be used to add
+	 * data to the Blob.
+	 *
+	 * @return a MonetBlob instance
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support MonetBlob objects that can be filled in
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.Blob createBlob() throws SQLException {
+		return new MonetBlob(new byte[1]);
+	}
 
-    /**
-     * Constructs an object that implements the NClob interface. The
-     * object returned initially contains no data. The setAsciiStream,
-     * setCharacterStream and setString methods of the NClob interface
-     * may be used to add data to the NClob.
-     *
-     * @return an NClob instance
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support MonetNClob objects that can be filled in
-     * @since 1.6
-     */
-    @Override
-    public java.sql.NClob createNClob() throws SQLException {
-        throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000");
-    }
+	/**
+	 * Constructs an object that implements the NClob interface. The
+	 * object returned initially contains no data. The setAsciiStream,
+	 * setCharacterStream and setString methods of the NClob interface
+	 * may be used to add data to the NClob.
+	 *
+	 * @return an NClob instance
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support MonetNClob objects that can be filled in
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.NClob createNClob() throws SQLException {
+		throw new SQLFeatureNotSupportedException("createNClob() not supported", "0A000");
+	}
 
-    /**
-     * Factory method for creating Struct objects.
-     *
-     * @param typeName the SQL type name of the SQL structured type that
-     *        this Struct object maps to. The typeName is the name of a
-     *        user-defined type that has been defined for this database.
-     *        It is the value returned by Struct.getSQLTypeName.
-     * @param attributes the attributes that populate the returned object
-     * @return a Struct object that maps to the given SQL type and is
-     *         populated with the given attributes
-     * @throws SQLException if a database error occurs, the typeName
-     *         is null or this method is called on a closed connection
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support this data type
-     * @since 1.6
-     */
-    @Override
-    public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException {
-        throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000");
-    }
+	/**
+	 * Factory method for creating Struct objects.
+	 *
+	 * @param typeName the SQL type name of the SQL structured type that
+	 *        this Struct object maps to. The typeName is the name of a
+	 *        user-defined type that has been defined for this database.
+	 *        It is the value returned by Struct.getSQLTypeName.
+	 * @param attributes the attributes that populate the returned object
+	 * @return a Struct object that maps to the given SQL type and is
+	 *         populated with the given attributes
+	 * @throws SQLException if a database error occurs, the typeName
+	 *         is null or this method is called on a closed connection
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support this data type
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+		throw new SQLFeatureNotSupportedException("createStruct() not supported", "0A000");
+	}
 
-    /**
-     * Constructs an object that implements the SQLXML interface. The
-     * object returned initially contains no data. The
-     * createXmlStreamWriter object and setString method of the SQLXML
-     * interface may be used to add data to the SQLXML object.
-     *
-     * @return An object that implements the SQLXML interface
-     * @throws SQLFeatureNotSupportedException the JDBC driver does
-     *         not support this data type
-     * @since 1.6
-     */
-    @Override
-    public java.sql.SQLXML createSQLXML() throws SQLException {
-        throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000");
-    }
+	/**
+	 * Constructs an object that implements the SQLXML interface. The
+	 * object returned initially contains no data. The
+	 * createXmlStreamWriter object and setString method of the SQLXML
+	 * interface may be used to add data to the SQLXML object.
+	 *
+	 * @return An object that implements the SQLXML interface
+	 * @throws SQLFeatureNotSupportedException the JDBC driver does
+	 *         not support this data type
+	 * @since 1.6
+	 */
+	@Override
+	public java.sql.SQLXML createSQLXML() throws SQLException {
+		throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000");
+	}
 
-    /**
-     * Returns true if the connection has not been closed and is still
-     * valid. The driver shall submit a query on the connection or use
-     * some other mechanism that positively verifies the connection is
-     * still valid when this method is called.
-     *
-     * The query submitted by the driver to validate the connection
-     * shall be executed in the context of the current transaction.
-     *
-     * @param timeout The time in seconds to wait for the database
-     *        operation used to validate the connection to complete. If
-     *        the timeout period expires before the operation completes,
-     *        this method returns false. A value of 0 indicates a
-     *        timeout is not applied to the database operation.
-     * @return true if the connection is valid, false otherwise
-     * @throws SQLException if the value supplied for timeout is less than 0
-     * @since 1.6
-     */
-    @Override
-    public boolean isValid(int timeout) throws SQLException {
-        if (timeout < 0)
-            throw new SQLException("timeout is less than 0", "M1M05");
-        if (closed)
-            return false;
+	/**
+	 * Returns true if the connection has not been closed and is still
+	 * valid. The driver shall submit a query on the connection or use
+	 * some other mechanism that positively verifies the connection is
+	 * still valid when this method is called.
+	 *
+	 * The query submitted by the driver to validate the connection
+	 * shall be executed in the context of the current transaction.
+	 *
+	 * @param timeout The time in seconds to wait for the database
+	 *        operation used to validate the connection to complete. If
+	 *        the timeout period expires before the operation completes,
+	 *        this method returns false. A value of 0 indicates a
+	 *        timeout is not applied to the database operation.
+	 * @return true if the connection is valid, false otherwise
+	 * @throws SQLException if the value supplied for timeout is less than 0
+	 * @since 1.6
+	 */
+	@Override
+	public boolean isValid(int timeout) throws SQLException {
+		if (timeout < 0)
+			throw new SQLException("timeout is less than 0", "M1M05");
+		if (closed)
+			return false;
 
-        // ping db using query: select 1;
-        Statement stmt = null;
-        ResultSet rs = null;
-        try {
-            stmt = createStatement();
-            stmt.setQueryTimeout(timeout);
-            rs = stmt.executeQuery("SELECT 1");
-            rs.close();
-            rs = null;
-            stmt.close();
-            return true;
-        } catch (Exception e) {
-            if (rs != null) {
-                try {
-                    rs.close();
-                } catch (Exception ignored) {}
-            }
-            if (stmt != null) {
-                try {
-                    stmt.close();
-                } catch (Exception ignored) {}
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns the value of the client info property specified by name.
-     * This method may return null if the specified client info property
-     * has not been set and does not have a default value.
-     * This method will also return null if the specified client info
-     * property name is not supported by the driver.
-     * Applications may use the DatabaseMetaData.getClientInfoProperties method
-     * to determine the client info properties supported by the driver.
-     *
-     * @param name - The name of the client info property to retrieve
-     * @return The value of the client info property specified or null
-     * @throws SQLException - if the database server returns an error
-     *	when fetching the client info value from the database
-     *	or this method is called on a closed connection
-     * @since 1.6
-     */
-    @Override
-    public String getClientInfo(String name) throws SQLException {
-        if (name == null || name.isEmpty())
-            return null;
-        return conn_props.getProperty(name);
-    }
+		// ping db using query: select 1;
+		Statement stmt = null;
+		ResultSet rs = null;
+		boolean isValid = false;
+		try {
+			stmt = createStatement();
+			if (stmt != null) {
+				int original_timeout = stmt.getQueryTimeout();
+				if (timeout > 0 && original_timeout != timeout) {
+					// we need to change the requested timeout for this test query
+					stmt.setQueryTimeout(timeout);
+				}
+				rs = stmt.executeQuery("SELECT 1");
+				if (rs != null && rs.next()) {
+					isValid = true;
+				}
+				if (timeout > 0 && original_timeout != timeout) {
+					// restore the original server timeout value
+					stmt.setQueryTimeout(original_timeout);
+				}
+			}
+		} catch (SQLException se) {
+			String msg = se.getMessage();
+			if (msg != null && msg.equals("Current transaction is aborted (please ROLLBACK)")) {
+				isValid = true;
+			}
+			/* ignore stmt errors/exceptions, we are only testing if the connection is still alive and usable */
+		} finally {
+			if (rs != null) {
+				try {
+					rs.close();
+				} catch (Exception e2) { /* ignore error */ }
+			}
+			if (stmt != null) {
+				try {
+					stmt.close();
+				} catch (Exception e2) { /* ignore error */ }
+			}
+		}
+		return isValid;
+	}
 
-    /**
-     * Returns a list containing the name and current value of each client info
-     * property supported by the driver. The value of a client info property may
-     * be null if the property has not been set and does not have a default value.
-     *
-     * @return A Properties object that contains the name and current value
-     *         of each of the client info properties supported by the driver.
-     * @throws SQLException - if the database server returns an error
-     *	when fetching the client info value from the database
-     *	or this method is called on a closed connection
-     * @since 1.6
-     */
-    @Override
-    public Properties getClientInfo() throws SQLException {
-        // return a clone of the connection properties object
-        return new Properties(conn_props);
-    }
+	/**
+	 * Returns the value of the client info property specified by name.
+	 * This method may return null if the specified client info property
+	 * has not been set and does not have a default value.
+	 * This method will also return null if the specified client info
+	 * property name is not supported by the driver.
+	 * Applications may use the DatabaseMetaData.getClientInfoProperties method
+	 * to determine the client info properties supported by the driver.
+	 *
+	 * @param name - The name of the client info property to retrieve
+	 * @return The value of the client info property specified or null
+	 * @throws SQLException - if the database server returns an error
+	 *	when fetching the client info value from the database
+	 *	or this method is called on a closed connection
+	 * @since 1.6
+	 */
+	@Override
+	public String getClientInfo(String name) throws SQLException {
+		if (name == null || name.isEmpty())
+			return null;
+		return conn_props.getProperty(name);
+	}
+
+	/**
+	 * Returns a list containing the name and current value of each client info
+	 * property supported by the driver. The value of a client info property may
+	 * be null if the property has not been set and does not have a default value.
+	 *
+	 * @return A Properties object that contains the name and current value
+	 *         of each of the client info properties supported by the driver.
+	 * @throws SQLException - if the database server returns an error
+	 *	when fetching the client info value from the database
+	 *	or this method is called on a closed connection
+	 * @since 1.6
+	 */
+	@Override
+	public Properties getClientInfo() throws SQLException {
+		// return a clone of the connection properties object
+		return new Properties(conn_props);
+	}
 
-    /**
-     * Sets the value of the client info property specified by name to the value specified by value.
-     * Applications may use the DatabaseMetaData.getClientInfoProperties method to determine
-     * the client info properties supported by the driver and the maximum length that may be specified
-     * for each property.
-     *
-     * The driver stores the value specified in a suitable location in the database. For example
-     * in a special register, session parameter, or system table column. For efficiency the driver
-     * may defer setting the value in the database until the next time a statement is executed
-     * or prepared. Other than storing the client information in the appropriate place in the
-     * database, these methods shall not alter the behavior of the connection in anyway.
-     * The values supplied to these methods are used for accounting, diagnostics and debugging purposes only.
-     *
-     * The driver shall generate a warning if the client info name specified is not recognized by the driver.
-     *
-     * If the value specified to this method is greater than the maximum length for the property
-     * the driver may either truncate the value and generate a warning or generate a SQLClientInfoException.
-     * If the driver generates a SQLClientInfoException, the value specified was not set on the connection.
-     *
-     * The following are standard client info properties. Drivers are not required to support these
-     * properties however if the driver supports a client info property that can be described by one
-     * of the standard properties, the standard property name should be used.
-     *
-     *	ApplicationName - The name of the application currently utilizing the connection
-     *	ClientUser - The name of the user that the application using the connection is performing work for.
-     *		This may not be the same as the user name that was used in establishing the connection.
-     *	ClientHostname - The hostname of the computer the application using the connection is running on.
-     *
-     * @param name - The name of the client info property to set
-     * @param value - The value to set the client info property to. If the
-     *        value is null, the current value of the specified property is cleared.
-     * @throws SQLClientInfoException - if the database server returns an error
-     *         while setting the clientInfo values on the database server
-     *         or this method is called on a closed connection
-     * @since 1.6
-     */
-    @Override
-    public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException {
-        if (name == null || name.isEmpty()) {
-            addWarning("setClientInfo: missing property name", "01M07");
-            return;
-        }
-        // If the value is null, the current value of the specified property is cleared.
-        if (value == null) {
-            if (conn_props.containsKey(name))
-                conn_props.remove(name);
-            return;
-        }
-        // only set value for supported property names
-        if (name.equals("host") || name.equals("port") || name.equals("user") || name.equals("password") ||
-                name.equals("database") || name.equals("language") || name.equals("so_timeout") ||
-                name.equals("hash") || name.equals("treat_blob_as_binary") || name.equals("follow_redirects") ||
-                name.equals("treat_clob_as_longvarchar") || name.equals("embedded") || name.equals("directory")) {
-            conn_props.setProperty(name, value);
-        } else {
-            addWarning("setClientInfo: " + name + "is not a recognised property", "01M07");
-        }
-    }
+	/**
+	 * Sets the value of the client info property specified by name to the value specified by value.
+	 * Applications may use the DatabaseMetaData.getClientInfoProperties method to determine
+	 * the client info properties supported by the driver and the maximum length that may be specified
+	 * for each property.
+	 *
+	 * The driver stores the value specified in a suitable location in the database. For example
+	 * in a special register, session parameter, or system table column. For efficiency the driver
+	 * may defer setting the value in the database until the next time a statement is executed
+	 * or prepared. Other than storing the client information in the appropriate place in the
+	 * database, these methods shall not alter the behavior of the connection in anyway.
+	 * The values supplied to these methods are used for accounting, diagnostics and debugging purposes only.
+	 *
+	 * The driver shall generate a warning if the client info name specified is not recognized by the driver.
+	 *
+	 * If the value specified to this method is greater than the maximum length for the property
+	 * the driver may either truncate the value and generate a warning or generate a SQLClientInfoException.
+	 * If the driver generates a SQLClientInfoException, the value specified was not set on the connection.
+	 *
+	 * The following are standard client info properties. Drivers are not required to support these
+	 * properties however if the driver supports a client info property that can be described by one
+	 * of the standard properties, the standard property name should be used.
+	 *
+	 *	ApplicationName - The name of the application currently utilizing the connection
+	 *	ClientUser - The name of the user that the application using the connection is performing work for.
+	 *		This may not be the same as the user name that was used in establishing the connection.
+	 *	ClientHostname - The hostname of the computer the application using the connection is running on.
+	 *
+	 * @param name - The name of the client info property to set
+	 * @param value - The value to set the client info property to. If the
+	 *        value is null, the current value of the specified property is cleared.
+	 * @throws SQLClientInfoException - if the database server returns an error
+	 *         while setting the clientInfo values on the database server
+	 *         or this method is called on a closed connection
+	 * @since 1.6
+	 */
+	@Override
+	public void setClientInfo(String name, String value) throws java.sql.SQLClientInfoException {
+		if (name == null || name.isEmpty()) {
+			addWarning("setClientInfo: missing property name", "01M07");
+			return;
+		}
+		// If the value is null, the current value of the specified property is cleared.
+		if (value == null) {
+			if (conn_props.containsKey(name))
+				conn_props.remove(name);
+			return;
+		}
+		// only set value for supported property names
+		if (name.equals("host") || name.equals("port") || name.equals("user") || name.equals("password") ||
+				name.equals("database") || name.equals("language") || name.equals("so_timeout") ||
+				name.equals("hash") || name.equals("treat_blob_as_binary") || name.equals("follow_redirects") ||
+				name.equals("treat_clob_as_longvarchar") || name.equals("embedded") || name.equals("directory")) {
+			conn_props.setProperty(name, value);
+		} else {
+			addWarning("setClientInfo: " + name + "is not a recognised property", "01M07");
+		}
+	}
 
-    /**
-     * Sets the value of the connection's client info properties.
-     * The Properties object contains the names and values of the client info
-     * properties to be set. The set of client info properties contained in the
-     * properties list replaces the current set of client info properties on the connection.
-     * If a property that is currently set on the connection is not present in the
-     * properties list, that property is cleared. Specifying an empty properties list
-     * will clear all of the properties on the connection.
-     * See setClientInfo (String, String) for more information.
-     *
-     * If an error occurs in setting any of the client info properties, a
-     * SQLClientInfoException is thrown. The SQLClientInfoException contains information
-     * indicating which client info properties were not set. The state of the client
-     * information is unknown because some databases do not allow multiple client info
-     * properties to be set atomically. For those databases, one or more properties may
-     * have been set before the error occurred.
-     *
-     * @param props - The list of client info properties to set
-     * @throws SQLClientInfoException - if the database server returns an error
-     *	while setting the clientInfo values on the database server
-     *	or this method is called on a closed connection
-     * @since 1.6
-     */
-    @Override
-    public void setClientInfo(Properties props) throws java.sql.SQLClientInfoException {
-        if (props != null) {
-            for (Map.Entry<Object, Object> entry : props.entrySet()) {
-                setClientInfo(entry.getKey().toString(), entry.getValue().toString());
-            }
-        }
-    }
+	/**
+	 * Sets the value of the connection's client info properties.
+	 * The Properties object contains the names and values of the client info
+	 * properties to be set. The set of client info properties contained in the
+	 * properties list replaces the current set of client info properties on the connection.
+	 * If a property that is currently set on the connection is not present in the
+	 * properties list, that property is cleared. Specifying an empty properties list
+	 * will clear all of the properties on the connection.
+	 * See setClientInfo (String, String) for more information.
+	 *
+	 * If an error occurs in setting any of the client info properties, a
+	 * SQLClientInfoException is thrown. The SQLClientInfoException contains information
+	 * indicating which client info properties were not set. The state of the client
+	 * information is unknown because some databases do not allow multiple client info
+	 * properties to be set atomically. For those databases, one or more properties may
+	 * have been set before the error occurred.
+	 *
+	 * @param props - The list of client info properties to set
+	 * @throws SQLClientInfoException - if the database server returns an error
+	 *	while setting the clientInfo values on the database server
+	 *	or this method is called on a closed connection
+	 * @since 1.6
+	 */
+	@Override
+	public void setClientInfo(Properties props) throws java.sql.SQLClientInfoException {
+		if (props != null) {
+			for (Map.Entry<Object, Object> entry : props.entrySet()) {
+				setClientInfo(entry.getKey().toString(), entry.getValue().toString());
+			}
+		}
+	}
 
-    //== Java 1.7 methods (JDBC 4.1)
+	/**
+	 * Sets the given schema name to access.
+	 *
+	 * @param schema the name of a schema in which to work
+	 * @throws SQLException if a database access error occurs or this method is called on a closed connection
+	 * @since 1.7
+	 */
+	@Override
+	public void setSchema(String schema) throws SQLException {
+		if (closed)
+			throw new SQLException("Cannot call on closed Connection", "M1M20");
+		if (schema == null)
+			throw new SQLException("Missing schema name", "M1M05");
 
-    /**
-     * Sets the given schema name to access.
-     *
-     * @param schema the name of a schema in which to work
-     * @throws SQLException if a database access error occurs or this method is called on a closed connection
-     * @since 1.7
-     */
-    @Override
-    public void setSchema(String schema) throws SQLException {
-        if (closed)
-            throw new SQLException("Cannot call on closed Connection", "M1M20");
-        if (schema == null)
-            throw new SQLException("Missing schema name", "M1M05");
-
-        try (Statement st = createStatement()) {
-            st.execute("SET SCHEMA \"" + schema + "\"");
-        }
-    }
+		Statement st = createStatement();
+		schema = schema.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'");
+		try {
+			st.execute("SET SCHEMA \"" + schema + "\"");
+		} finally {
+			st.close();
+		}
+	}
 
-    /**
-     * Retrieves this Connection object's current schema name.
-     *
-     * @return the current schema name or null if there is none
-     * @throws SQLException if a database access error occurs or this method is called on a closed connection
-     */
-    @Override
-    public String getSchema() throws SQLException {
-        if (closed) {
-            throw new SQLException("Cannot call on closed Connection", "M1M20");
-        }
-        String cur_schema;
-        Statement st = createStatement();
-        ResultSet rs = null;
-        try {
-            rs = st.executeQuery("SELECT CURRENT_SCHEMA");
-            if (!rs.next())
-                throw new SQLException("Row expected", "02000");
-            cur_schema = rs.getString(1);
-        } finally {
-            if (rs != null)
-                rs.close();
-            st.close();
-        }
-        return cur_schema;
-    }
+	/**
+	 * Retrieves this Connection object's current schema name.
+	 *
+	 * @return the current schema name or null if there is none
+	 * @throws SQLException if a database access error occurs or this method is called on a closed connection
+	 */
+	@Override
+	public String getSchema() throws SQLException {
+		if (closed) {
+			throw new SQLException("Cannot call on closed Connection", "M1M20");
+		}
+		String cur_schema;
+		Statement st = createStatement();
+		ResultSet rs = null;
+		try {
+			rs = st.executeQuery("SELECT CURRENT_SCHEMA");
+			if (!rs.next())
+				throw new SQLException("Row expected", "02000");
+			cur_schema = rs.getString(1);
+		} finally {
+			if (rs != null)
+				rs.close();
+			st.close();
+		}
+		return cur_schema;
+	}
 
-    /**
-     * Terminates an open connection. Calling abort results in:
-     *  * The connection marked as closed
-     *  * Closes any physical connection to the database
-     *  * Releases resources used by the connection
-     *  * Insures that any thread that is currently accessing the
-     *    connection will either progress to completion or throw an
-     *    SQLException.
-     * Calling abort marks the connection closed and releases any
-     * resources. Calling abort on a closed connection is a no-op.
-     *
-     * @param executor The Executor implementation which will be used by abort
-     * @throws SQLException if a database access error occurs or the executor is null
-     * @throws SecurityException if a security manager exists and its checkPermission method denies calling abort
-     */
-    @Override
-    public void abort(Executor executor) throws SQLException {
-        if (closed)
-            return;
-        if (executor == null)
-            throw new SQLException("executor is null", "M1M05");
-        // this is really the simplest thing to do, it destroys
-        // everything (in particular the server connection)
-        close();
-    }
+	/**
+	 * Terminates an open connection. Calling abort results in:
+	 *  * The connection marked as closed
+	 *  * Closes any physical connection to the database
+	 *  * Releases resources used by the connection
+	 *  * Insures that any thread that is currently accessing the
+	 *    connection will either progress to completion or throw an
+	 *    SQLException.
+	 * Calling abort marks the connection closed and releases any
+	 * resources. Calling abort on a closed connection is a no-op.
+	 *
+	 * @param executor The Executor implementation which will be used by abort
+	 * @throws SQLException if a database access error occurs or the executor is null
+	 * @throws SecurityException if a security manager exists and its checkPermission method denies calling abort
+	 */
+	@Override
+	public void abort(Executor executor) throws SQLException {
+		if (closed)
+			return;
+		if (executor == null)
+			throw new SQLException("executor is null", "M1M05");
+		// this is really the simplest thing to do, it destroys
+		// everything (in particular the server connection)
+		close();
+	}
 
-    /**
-     * Sets the maximum period a Connection or objects created from the
-     * Connection will wait for the database to reply to any one
-     * request. If any request remains unanswered, the waiting method
-     * will return with a SQLException, and the Connection or objects
-     * created from the Connection will be marked as closed. Any
-     * subsequent use of the objects, with the exception of the close,
-     * isClosed or Connection.isValid methods, will result in a
-     * SQLException.
-     *
-     * @param executor The Executor implementation which will be used by setNetworkTimeout
-     * @param millis The time in milliseconds to wait for the database operation to complete
-     * @throws SQLException if a database access error occurs, this method is called on a closed connection, the
-     * executor is null, or the value specified for seconds is less than 0.
-     */
-    @Override
-    public void setNetworkTimeout(Executor executor, int millis) throws SQLException {
-        if (closed) {
-            throw new SQLException("Cannot call on closed Connection", "M1M20");
-        }
-        if (executor == null)
-            throw new SQLException("executor is null", "M1M05");
-        if (millis < 0)
-            throw new SQLException("milliseconds is less than zero", "M1M05");
-        this.setSoTimeout(millis);
-    }
+	/**
+	 * Sets the maximum period a Connection or objects created from the
+	 * Connection will wait for the database to reply to any one
+	 * request. If any request remains unanswered, the waiting method
+	 * will return with a SQLException, and the Connection or objects
+	 * created from the Connection will be marked as closed. Any
+	 * subsequent use of the objects, with the exception of the close,
+	 * isClosed or Connection.isValid methods, will result in a
+	 * SQLException.
+	 *
+	 * @param executor The Executor implementation which will be used by setNetworkTimeout
+	 * @param millis The time in milliseconds to wait for the database operation to complete
+	 * @throws SQLException if a database access error occurs, this method is called on a closed connection, the
+	 * executor is null, or the value specified for seconds is less than 0.
+	 */
+	@Override
+	public void setNetworkTimeout(Executor executor, int millis) throws SQLException {
+		if (closed)
+			throw new SQLException("Cannot call on closed Connection", "M1M20");
+		if (executor == null)
+			throw new SQLException("executor is null", "M1M05");
+		if (millis < 0)
+			throw new SQLException("milliseconds is less than zero", "M1M05");
+
+		try {
+			this.setSoTimeout(millis);
+		} catch (SocketException e) {
+			throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
+		}
+	}
 
-    /**
-     * Retrieves the number of milliseconds the driver will wait for a database request to complete. If the limit is
-     * exceeded, a SQLException is thrown.
-     *
-     * @return the current timeout limit in milliseconds; zero means there is no limit
-     * @throws SQLException if a database access error occurs or this method is called on a closed Connection
-     */
-    @Override
-    public int getNetworkTimeout() throws SQLException {
-        if (closed) {
-            throw new SQLException("Cannot call on closed Connection", "M1M20");
-        }
-        return this.getSoTimeout();
-    }
+	/**
+	 * Retrieves the number of milliseconds the driver will wait for a
+	 * database request to complete. If the limit is exceeded, a
+	 * SQLException is thrown.
+	 *
+	 * @return the current timeout limit in milliseconds; zero means
+	 *         there is no limit
+	 * @throws SQLException if a database access error occurs or
+	 *         this method is called on a closed Connection
+	 * @since 1.7
+	 */
+	@Override
+	public int getNetworkTimeout() throws SQLException {
+		if (closed)
+			throw new SQLException("Cannot call on closed Connection", "M1M20");
 
-    //== end methods of interface Connection
+		try {
+			return this.getSoTimeout();
+		} catch (SocketException e) {
+			throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
+		}
+	}
+
+	//== end methods of interface Connection
 
-    /**
-     * Returns whether the BLOB type should be mapped to BINARY type.
-     */
-    public boolean getBlobAsBinary() {
-        return blobIsBinary;
-    }
+	/**
+	 * Returns whether the BLOB type should be mapped to BINARY type.
+	 */
+	public boolean getBlobAsBinary() {
+		return blobIsBinary;
+	}
 
-    /**
-     * Returns whether the CLOB type should be mapped to LONGVARCHAR type.
-     */
-    public boolean getClobAsLongChar() {
-        return clobIsLongChar;
-    }
+	/**
+	 * Returns whether the CLOB type should be mapped to LONGVARCHAR type.
+	 */
+	public boolean getClobAsLongChar() {
+		return clobIsLongChar;
+	}
 
-    /**
-     * Sends the given string to MonetDB as regular statement, making sure there is a prompt after the command is sent.
-     * All possible returned information is discarded. Encountered errors are reported.
-     *
-     * @param command the exact string to send to MonetDB
-     * @throws SQLException if an IO exception or a database error occurs
-     */
-    void sendIndependentCommand(String command) throws SQLException {
-        try {
-            protocol.writeNextQuery(language.getQueryTemplateIndex(0), command, language.getQueryTemplateIndex(1));
-            protocol.waitUntilPrompt();
-            int csrh = protocol.getCurrentServerResponse();
-            if (csrh == ServerResponses.ERROR) {
-                String error = protocol.getRemainingStringLine(0);
-                throw new SQLException(error.substring(6), error.substring(0, 5));
-            }
-        } catch (SocketTimeoutException e) {
-            close(); // JDBC 4.1 semantics: abort()
-            throw new SQLException("connection timed out", "08M33");
-        } catch (IOException e) {
-            throw new SQLException(e.getMessage(), "08000");
-        }
-    }
+	/**
+	 * Sends the given string to MonetDB as special transaction command.
+	 * All possible returned information is discarded.
+	 * Encountered errors are reported.
+	 *
+	 * @param command the exact string to send to MonetDB
+	 * @throws SQLException if an IO exception or a database error occurs
+	 */
+	private void sendTransactionCommand(String command) throws SQLException {
+		// create a container for the result
+		ResponseList l = new ResponseList(0, 0, ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);
+		// send the appropriate query string to the database
+		try {
+			l.processQuery(command);
+		} finally {
+			l.close();
+		}
+	}
 
-    /**
-     * Adds a warning to the pile of warnings this Connection object has. If there were no warnings (or clearWarnings
-     * was called) this warning will be the first, otherwise this warning will get appended to the current warning.
-     *
-     * @param reason the warning message
-     */
-    protected void addWarning(String reason, String sqlstate) {
-        if (warnings == null) {
-            warnings = new SQLWarning(reason, sqlstate);
-        } else {
-            warnings.setNextWarning(new SQLWarning(reason, sqlstate));
-        }
-    }
+	/**
+	 * Sends the given string to MonetDB as regular statement, making sure there is a prompt after the command is sent.
+	 * All possible returned information is discarded. Encountered errors are reported.
+	 *
+	 * @param command the exact string to send to MonetDB
+	 * @throws SQLException if an IO exception or a database error occurs
+	 */
+	void sendIndependentCommand(String command) throws SQLException {
+		try {
+			protocol.writeNextQuery(language.getQueryTemplateIndex(0), command, language.getQueryTemplateIndex(1));
+			protocol.waitUntilPrompt();
+			int csrh = protocol.getCurrentServerResponse();
+			if (csrh == ServerResponses.ERROR) {
+				String error = protocol.getRemainingStringLine(0);
+				throw new SQLException(error.substring(6), error.substring(0, 5));
+			}
+		} catch (SocketTimeoutException e) {
+			close(); // JDBC 4.1 semantics: abort()
+			throw new SQLNonTransientConnectionException("connection timed out", "08M33");
+		} catch (IOException e) {
+			throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
+		}
+	}
 
-    /**
-     * A list of Response objects. Responses are added to this list. Methods of this class are not synchronized. This is
-     * left as responsibility to the caller to prevent concurrent access.
-     */
-    public class ResponseList {
+	/**
+	 * Adds a warning to the pile of warnings this Connection object has. If there were no warnings (or clearWarnings
+	 * was called) this warning will be the first, otherwise this warning will get appended to the current warning.
+	 *
+	 * @param reason the warning message
+	 */
+	void addWarning(String reason, String sqlstate) {
+		if (warnings == null) {
+			warnings = new SQLWarning(reason, sqlstate);
+		} else {
+			warnings.setNextWarning(new SQLWarning(reason, sqlstate));
+		}
+	}
 
-        /** The cache size (number of rows in a DataBlockResponse object) */
-        private final int cachesize;
-        /** The maximum number of results for this query */
-        private final int maxrows;
-        /** The ResultSet type to produce */
-        private final int rstype;
-        /** The ResultSet concurrency to produce */
-        private final int rsconcur;
-        /** The sequence number of this ResponseList */
-        private final int seqnr;
-        /** A list of the Responses associated with the query, in the right order */
-        private final List<IResponse> responses = new ArrayList<>();
-        /** A map of ResultSetResponses, used for additional DataBlockResponse mapping */
-        private Map<Integer, ResultSetResponse> rsresponses;
-        /** The current header returned by getNextResponse() */
-        private int curResponse = -1;
+	/**
+	 * A list of Response objects. Responses are added to this list. Methods of this class are not synchronized. This is
+	 * left as responsibility to the caller to prevent concurrent access.
+	 */
+	public class ResponseList {
 
-        /**
-         * Main constructor. The query argument can either be a String or List.  An SQLException is thrown if another
-         * object instance is supplied.
-         *
-         * @param cachesize overall cachesize to use
-         * @param maxrows maximum number of rows to allow in the set
-         * @param rstype the type of result sets to produce
-         * @param rsconcur the concurrency of result sets to produce
-         */
-        ResponseList(int cachesize, int maxrows, int rstype, int rsconcur) {
-            this.cachesize = cachesize;
-            this.maxrows = maxrows;
-            this.rstype = rstype;
-            this.rsconcur = rsconcur;
-            this.seqnr = SeqCounter++;
-        }
+		/** The cache size (number of rows in a DataBlockResponse object) */
+		private final int cachesize;
+		/** The maximum number of results for this query */
+		private final int maxrows;
+		/** The ResultSet type to produce */
+		private final int rstype;
+		/** The ResultSet concurrency to produce */
+		private final int rsconcur;
+		/** The sequence number of this ResponseList */
+		private final int seqnr;
+		/** A list of the Responses associated with the query, in the right order */
+		private final List<IResponse> responses = new ArrayList<>();
+		/** A map of ResultSetResponses, used for additional DataBlockResponse mapping */
+		private Map<Integer, ResultSetResponse> rsresponses;
+		/** The current header returned by getNextResponse() */
+		private int curResponse = -1;
 
-        public int getCachesize() {
-            return cachesize;
-        }
-
-        public int getRstype() {
-            return rstype;
-        }
+		/**
+		 * Main constructor. The query argument can either be a String or List.  An SQLException is thrown if another
+		 * object instance is supplied.
+		 *
+		 * @param cachesize overall cachesize to use
+		 * @param maxrows maximum number of rows to allow in the set
+		 * @param rstype the type of result sets to produce
+		 * @param rsconcur the concurrency of result sets to produce
+		 */
+		ResponseList(int cachesize, int maxrows, int rstype, int rsconcur) {
+			this.cachesize = cachesize;
+			this.maxrows = maxrows;
+			this.rstype = rstype;
+			this.rsconcur = rsconcur;
+			this.seqnr = SeqCounter++;
+		}
 
-        public int getRsconcur() {
-            return rsconcur;
-        }
+		public int getCachesize() {
+			return cachesize;
+		}
+
+		public int getRstype() {
+			return rstype;
+		}
 
-        public int getMaxrows() {
-            return maxrows;
-        }
+		public int getRsconcur() {
+			return rsconcur;
+		}
+
+		public int getMaxrows() {
+			return maxrows;
+		}
 
-        /**
-         * Retrieves the next available response, or null if there are no more responses.
-         *
-         * @return the next Response available or null
-         */
-        IResponse getNextResponse() throws SQLException {
-            if (rstype == ResultSet.TYPE_FORWARD_ONLY) {
-                // free resources if we're running forward only
-                if (curResponse >= 0 && curResponse < responses.size()) {
-                    IResponse tmp = responses.get(curResponse);
-                    if (tmp != null) {
-                        tmp.close();
-                    }
-                    responses.set(curResponse, null);
-                }
-            }
-            curResponse++;
-            if (curResponse >= responses.size()) {
-                // ResponseList is obviously completed so, there are no more responses
-                return null;
-            } else {
-                // return this response
-                return responses.get(curResponse);
-            }
-        }
+		/**
+		 * Retrieves the next available response, or null if there are no more responses.
+		 *
+		 * @return the next Response available or null
+		 */
+		IResponse getNextResponse() throws SQLException {
+			if (rstype == ResultSet.TYPE_FORWARD_ONLY) {
+				// free resources if we're running forward only
+				if (curResponse >= 0 && curResponse < responses.size()) {
+					IResponse tmp = responses.get(curResponse);
+					if (tmp != null) {
+						tmp.close();
+					}
+					responses.set(curResponse, null);
+				}
+			}
+			curResponse++;
+			if (curResponse >= responses.size()) {
+				// ResponseList is obviously completed so, there are no more responses
+				return null;
+			} else {
+				// return this response
+				return responses.get(curResponse);
+			}
+		}
 
-        /**
-         * Closes the Response at index i, if not null.
-         *
-         * @param i the index position of the header to close
-         */
-        void closeResponse(int i) {
-            if (i < 0 || i >= responses.size()) return;
-            IResponse tmp = responses.set(i, null);
-            if (tmp != null)
-                tmp.close();
-        }
-
-        /**
-         * Closes the current response.
-         */
-        void closeCurrentResponse() {
-            closeResponse(curResponse);
-        }
+		/**
+		 * Closes the Response at index i, if not null.
+		 *
+		 * @param i the index position of the header to close
+		 */
+		void closeResponse(int i) {
+			if (i < 0 || i >= responses.size()) return;
+			IResponse tmp = responses.set(i, null);
+			if (tmp != null)
+				tmp.close();
+		}
 
-        /**
-         * Closes the current and previous responses.
-         */
-        void closeCurOldResponses() {
-            for (int i = curResponse; i >= 0; i--) {
-                closeResponse(i);
-            }
-        }
+		/**
+		 * Closes the current response.
+		 */
+		void closeCurrentResponse() {
+			closeResponse(curResponse);
+		}
 
-        /**
-         * Closes this ResponseList by closing all the Responses in this ResponseList.
-         */
-        public void close() {
-            for (int i = 0; i < responses.size(); i++) {
-                closeResponse(i);
-            }
-        }
+		/**
+		 * Closes the current and previous responses.
+		 */
+		void closeCurOldResponses() {
+			for (int i = curResponse; i >= 0; i--) {
+				closeResponse(i);
+			}
+		}
 
-        /**
-         * Returns whether this ResponseList has still unclosed Responses.
-         */
-        boolean hasUnclosedResponses() {
-            for (IResponse r : responses) {
-                if (r != null)
-                    return true;
-            }
-            return false;
-        }
+		/**
+		 * Closes this ResponseList by closing all the Responses in this ResponseList.
+		 */
+		public void close() {
+			for (int i = 0; i < responses.size(); i++) {
+				closeResponse(i);
+			}
+		}
 
-        /**
-         * Executes the query contained in this ResponseList, and stores the Responses resulting from this query in this
-         * ResponseList.
-         *
-         * @throws SQLException if a database error occurs
-         */
-        void processQuery(String query) throws SQLException {
-            this.executeQuery(language.getQueryTemplates(), query);
-        }
-
-        /**
-         * Internal executor of queries.
-         *
-         * @param templ the template to fill in
-         * @param query the query to execute
-         * @throws SQLException if a database error occurs
-         */
-        @SuppressWarnings("fallthrough")
-        public void executeQuery(String[] templ, String query) throws SQLException {
-            String error = null;
+		/**
+		 * Returns whether this ResponseList has still unclosed Responses.
+		 */
+		boolean hasUnclosedResponses() {
+			for (IResponse r : responses) {
+				if (r != null)
+					return true;
+			}
+			return false;
+		}
 
-            try {
-                // make sure we're ready to send query; read data till we have the prompt it is possible (and most
-                // likely) that we already have the prompt and do not have to skip any lines. Ignore errors from
-                // previous result sets.
-                protocol.waitUntilPrompt();
+		/**
+		 * Executes the query contained in this ResponseList, and stores the Responses resulting from this query in this
+		 * ResponseList.
+		 *
+		 * @throws SQLException if a database error occurs
+		 */
+		void processQuery(String query) throws SQLException {
+			this.executeQuery(language.getQueryTemplates(), query);
+		}
 
-                // {{{ set reply size
-                /*
-                 * Change the reply size of the server.  If the given value is the same as the current value known
-                 * to use, then ignore this call.  If it is set to 0 we get a prompt after the server sent it's
-                 * header.
-                 *
-                 * 2017: For now, in the embedded connection, the value set cachesize will be always the default one.
-                 */
-                int size = (cachesize != 0 && !isEmbedded) ? cachesize : MonetConnection.this.getDefFetchsize();
-                size = maxrows != 0 ? Math.min(maxrows, size) : size;
-                // don't do work if it's not needed
-                if (!isEmbedded && language.getRepresentation().equals("sql") && size != curReplySize &&
-                        !Arrays.deepEquals(templ, language.getCommandTemplates())) {
-                    sendControlCommand(ControlCommands.REPLY_SIZE, size);
-                    // store the reply size after a successful change
-                    curReplySize = size;
-                }
-                // }}} set reply size
+		/**
+		 * Internal executor of queries.
+		 *
+		 * @param templ the template to fill in
+		 * @param query the query to execute
+		 * @throws SQLException if a database error occurs
+		 */
+		@SuppressWarnings("fallthrough")
+		public void executeQuery(String[] templ, String query) throws SQLException {
+			String error = null;
+
+			try {
+				// make sure we're ready to send query; read data till we have the prompt it is possible (and most
+				// likely) that we already have the prompt and do not have to skip any lines. Ignore errors from
+				// previous result sets.
+				protocol.waitUntilPrompt();
 
-                // If the query is larger than the TCP buffer size, use a special send thread to avoid deadlock with
-                // the server due to blocking behaviour when the buffer is full. Because the server will be writing
-                // back results to us, it will eventually block as well when its TCP buffer gets full, as we are
-                // blocking an not consuming from it. The result is a state where both client and server want to
-                // write, but block.
-                if (query.length() > getBlockSize()) {
-                    // get a reference to the send thread
-                    if (senderThread == null) {
-                        senderThread = new SenderThread(protocol);
-                    }
-                    // tell it to do some work!
-                    senderThread.runQuery(templ, query);
-                } else {
-                    // this is a simple call, which is a lot cheaper and will always succeed for small queries.
-                    protocol.writeNextQuery((templ[0] == null) ? "" : templ[0], query,
-                            (templ[1] == null) ? "" : templ[1]);
-                }
+				// {{{ set reply size
+				/*
+				 * Change the reply size of the server.  If the given value is the same as the current value known
+				 * to use, then ignore this call.  If it is set to 0 we get a prompt after the server sent it's
+				 * header.
+				 *
+				 * 2017: For now, in the embedded connection, the value set cachesize will be always the default one.
+				 */
+				int size = (cachesize != 0 && !isEmbedded) ? cachesize : MonetConnection.this.getDefFetchsize();
+				size = maxrows != 0 ? Math.min(maxrows, size) : size;
+				// don't do work if it's not needed
+				if (!isEmbedded && language.getRepresentation().equals("sql") && size != curReplySize &&
+						!Arrays.deepEquals(templ, language.getCommandTemplates())) {
+					sendControlCommand(ControlCommands.REPLY_SIZE, size);
+					// store the reply size after a successful change
+					curReplySize = size;
+				}
+				// }}} set reply size
 
-                // go for new results
-                protocol.fetchNextResponseData();
-                int nextResponse = protocol.getCurrentServerResponse();
-                IResponse res = null;
-                while (nextResponse != ServerResponses.PROMPT) {
-                    // each response should start with a start of header (or error)
-                    switch (nextResponse) {
-                        case ServerResponses.SOHEADER:
-                            // make the response object, and fill it
-                            int nextStartHeader = protocol.getNextStarterHeader();
-                            try {
-                                switch (nextStartHeader) {
-                                    case StarterHeaders.Q_PARSE:
-                                        throw new ProtocolException("Q_PARSE header not allowed here");
-                                    case StarterHeaders.Q_TABLE:
-                                    case StarterHeaders.Q_PREPARE: {
-                                        res = protocol.getNextResultSetResponse(MonetConnection.this,
-                                                ResponseList.this, this.seqnr, this.maxrows);
-                                        ResultSetResponse rsreponse = (ResultSetResponse) res;
-                                        if (rsresponses == null) {
-                                            rsresponses = new HashMap<>();
-                                        }
-                                        rsresponses.put(rsreponse.getId(), rsreponse);
-                                    }
-                                    break;
-                                    case StarterHeaders.Q_UPDATE:
-                                        res = protocol.getNextUpdateResponse();
-                                        break;
-                                    case StarterHeaders.Q_SCHEMA:
-                                        res = protocol.getNextSchemaResponse();
-                                        break;
-                                    case StarterHeaders.Q_TRANS:
-                                        res = protocol.getNextAutoCommitResponse();
-                                        boolean isAutoCommit = ((AutoCommitResponse) res).isAutocommit();
+				// If the query is larger than the TCP buffer size, use a special send thread to avoid deadlock with
+				// the server due to blocking behaviour when the buffer is full. Because the server will be writing
+				// back results to us, it will eventually block as well when its TCP buffer gets full, as we are
+				// blocking an not consuming from it. The result is a state where both client and server want to
+				// write, but block.
+				if (query.length() > getBlockSize()) {
+					// get a reference to the send thread
+					if (senderThread == null) {
+						senderThread = new SenderThread(protocol);
+					}
+					// tell it to do some work!
+					senderThread.runQuery(templ, query);
+				} else {
+					// this is a simple call, which is a lot cheaper and will always succeed for small queries.
+					protocol.writeNextQuery((templ[0] == null) ? "" : templ[0], query,
+							(templ[1] == null) ? "" : templ[1]);
+				}
+
+				// go for new results
+				protocol.fetchNextResponseData();
+				int nextResponse = protocol.getCurrentServerResponse();
+				IResponse res = null;
+				while (nextResponse != ServerResponses.PROMPT) {
+					// each response should start with a start of header (or error)
+					switch (nextResponse) {
+						case ServerResponses.SOHEADER:
+							// make the response object, and fill it
+							int nextStartHeader = protocol.getNextStarterHeader();
+							try {
+								switch (nextStartHeader) {
+									case StarterHeaders.Q_PARSE:
+										throw new ProtocolException("Q_PARSE header not allowed here");
+									case StarterHeaders.Q_TABLE:
+									case StarterHeaders.Q_PREPARE: {
+										res = protocol.getNextResultSetResponse(MonetConnection.this,
+												ResponseList.this, this.seqnr, this.maxrows);
+										ResultSetResponse rsreponse = (ResultSetResponse) res;
+										if (rsresponses == null) {
+											rsresponses = new HashMap<>();
+										}
+										rsresponses.put(rsreponse.getId(), rsreponse);
+									}
+									break;
+									case StarterHeaders.Q_UPDATE:
+										res = protocol.getNextUpdateResponse();
+										break;
+									case StarterHeaders.Q_SCHEMA:
+										res = protocol.getNextSchemaResponse();
+										break;
+									case StarterHeaders.Q_TRANS:
+										res = protocol.getNextAutoCommitResponse();
+										boolean isAutoCommit = ((AutoCommitResponse) res).isAutocommit();
 
-                                        if (MonetConnection.this.getAutoCommit() && isAutoCommit) {
-                                            MonetConnection.this.addWarning("Server enabled auto commit mode " +
-                                                    "while local state already was auto commit.", "01M11");
-                                        }
-                                        MonetConnection.this.autoCommit = isAutoCommit;
-                                        break;
-                                    case StarterHeaders.Q_BLOCK: {
-                                        AbstractDataBlockResponse next = protocol.getNextDatablockResponse(rsresponses);
-                                        if (next == null) {
-                                            error = "M0M12!No ResultSetResponse for a DataBlock found";
-                                            break;
-                                        }
-                                        res = next;
-                                    }
-                                    break;
-                                }
-                            } catch (ProtocolException e) {
-                                error = "M0M10!error while parsing start of header:\n" + e.getMessage() + " found: '"
-                                        + protocol.getRemainingStringLine(0).charAt(e.getErrorOffset()) + "'" +
-                                        " in: \"" + protocol.getRemainingStringLine(0) + "\"" + " at pos: "
-                                        + e.getErrorOffset();
-                                // flush all the rest
-                                protocol.waitUntilPrompt();
-                                nextResponse = protocol.getCurrentServerResponse();
-                                break;
-                            }
+										if (MonetConnection.this.getAutoCommit() && isAutoCommit) {
+											MonetConnection.this.addWarning("Server enabled auto commit mode " +
+													"while local state already was auto commit.", "01M11");
+										}
+										MonetConnection.this.autoCommit = isAutoCommit;
+										break;
+									case StarterHeaders.Q_BLOCK: {
+										AbstractDataBlockResponse next = protocol.getNextDatablockResponse(rsresponses);
+										if (next == null) {
+											error = "M0M12!No ResultSetResponse for a DataBlock found";
+											break;
+										}
+										res = next;
+									}
+									break;
+								}
+							} catch (ProtocolException e) {
+								error = "M0M10!error while parsing start of header:\n" + e.getMessage() + " found: '"
+										+ protocol.getRemainingStringLine(0).charAt(e.getErrorOffset()) + "'" +
+										" in: \"" + protocol.getRemainingStringLine(0) + "\"" + " at pos: "
+										+ e.getErrorOffset();
+								// flush all the rest
+								protocol.waitUntilPrompt();
+								nextResponse = protocol.getCurrentServerResponse();
+								break;
+							}
+							// immediately handle errors after parsing the header (res may be null)
+							if (error != null) {
+								protocol.waitUntilPrompt();
+								nextResponse = protocol.getCurrentServerResponse();
+								break;
+							}
+							// here we have a res object, which we can start filling
+							if (res instanceof IIncompleteResponse) {
+								IIncompleteResponse iter = (IIncompleteResponse) res;
+								while (iter.wantsMore()) {
+									try {
+										protocol.fetchNextResponseData();
+										iter.addLines(protocol);
+									} catch (ProtocolException ex) {
+										// right, some protocol violation, skip the rest of the result
+										error = "M0M10!" + ex.getMessage();
+										protocol.waitUntilPrompt();
+										nextResponse = protocol.getCurrentServerResponse();
+										break;
+									}
+								}
+							}
 
-                            // immediately handle errors after parsing the header (res may be null)
-                            if (error != null) {
-                                protocol.waitUntilPrompt();
-                                nextResponse = protocol.getCurrentServerResponse();
-                                break;
-                            }
-
-                            // here we have a res object, which we can start filling
-                            if (res instanceof IIncompleteResponse) {
-                                IIncompleteResponse iter = (IIncompleteResponse) res;
-                                while (iter.wantsMore()) {
-                                    try {
-                                        protocol.fetchNextResponseData();
-                                        iter.addLines(protocol);
-                                    } catch (ProtocolException ex) {
-                                        // right, some protocol violation, skip the rest of the result
-                                        error = "M0M10!" + ex.getMessage();
-                                        protocol.waitUntilPrompt();
-                                        nextResponse = protocol.getCurrentServerResponse();
-                                        break;
-                                    }
-                                }
-                            }
-
-                            if (error != null) {
-                                break;
-                            }
+							if (error != null) {
+								break;
+							}
 
-                            // it is of no use to store DataBlockResponses, you never want to retrieve them directly
-                            // anyway
-                            if (!(res instanceof AbstractDataBlockResponse)) {
-                                responses.add(res);
-                            }
-                            // read the next line (can be prompt, new result, error, etc.) before we start the loop over
-                            protocol.fetchNextResponseData();
-                            nextResponse = protocol.getCurrentServerResponse();
-                            break;
-                        case ServerResponses.INFO:
-                            addWarning(protocol.getRemainingStringLine(0), "01000");
-                            // read the next line (can be prompt, new result, error, etc.) before we start the loop over
-                            protocol.fetchNextResponseData();
-                            nextResponse = protocol.getCurrentServerResponse();
-                            break;
-                        case ServerResponses.ERROR:
-                            // read everything till the prompt (should be error) we don't know if we ignore some
-                            // garbage here... but the log should reveal that
-                            error = protocol.getRemainingStringLine(0);
-                            protocol.waitUntilPrompt();
-                            nextResponse = protocol.getCurrentServerResponse();
-                            break;
-                        default:
-                            throw new SQLException("Protocol violation, unexpected line!", "M0M10");
-                    }
-                }
+							// it is of no use to store DataBlockResponses, you never want to retrieve them directly
+							// anyway
+							if (!(res instanceof AbstractDataBlockResponse)) {
+								responses.add(res);
+							}
+							// read the next line (can be prompt, new result, error, etc.) before we start the loop over
+							protocol.fetchNextResponseData();
+							nextResponse = protocol.getCurrentServerResponse();
+							break;
+						case ServerResponses.INFO:
+							addWarning(protocol.getRemainingStringLine(0), "01000");
+							// read the next line (can be prompt, new result, error, etc.) before we start the loop over
+							protocol.fetchNextResponseData();
+							nextResponse = protocol.getCurrentServerResponse();
+							break;
+						case ServerResponses.ERROR:
+							// read everything till the prompt (should be error) we don't know if we ignore some
+							// garbage here... but the log should reveal that
+							error = protocol.getRemainingStringLine(0);
+							protocol.waitUntilPrompt();
+							nextResponse = protocol.getCurrentServerResponse();
+							break;
+						default:
+							throw new SQLException("Protocol violation, unexpected line!", "M0M10");
+					}
+				}
 
-                // if we used the senderThread, make sure it has finished
-                if (senderThread != null) {
-                    String tmp = senderThread.getErrors();
-                    if (tmp != null) {
-                        if (error == null) {
-                            error = "08000!" + tmp;
-                        } else {
-                            error += "\n08000!" + tmp;
-                        }
-                    }
-                }
-                if (error != null) {
-                    SQLException ret = null;
-                    String[] errorsList = error.split("\n");
-                    for (String singleError : errorsList) {
-                        String reason = isEmbedded() ? singleError : singleError.substring(6);
-                        String sqlState = isEmbedded() ? "M0M10" : singleError.substring(0, 5);
-                        if (ret == null) {
-                            ret = new SQLException(reason, sqlState);
-                        } else {
-                            ret.setNextException(new SQLException(reason, sqlState));
-                        }
-                    }
-                    throw ret;
-                }
-            } catch (SocketTimeoutException e) {
-                this.close(); // JDBC 4.1 semantics, abort()
-                throw new SQLException("connection timed out", "08M33");
-            } catch (IOException e) {
-                closed = true;
-                throw new SQLException(e.getMessage() + " (mserver still alive?)", "08000");
-            }
-        }
-    }
+				// if we used the senderThread, make sure it has finished
+				if (senderThread != null) {
+					String tmp = senderThread.getErrors();
+					if (tmp != null) {
+						if (error == null) {
+							error = "08000!" + tmp;
+						} else {
+							error += "\n08000!" + tmp;
+						}
+					}
+				}
+				if (error != null) {
+					SQLException ret = null;
+					String[] errorsList = error.split("\n");
+					for (String singleError : errorsList) {
+						SQLException newErr;
+						String reason = isEmbedded() ? singleError : singleError.substring(6);
+						String sqlState = isEmbedded() ? "M0M10" : singleError.substring(0, 5);
+						if (singleError.length() >= 6) {
+							newErr = new SQLException(reason, sqlState);
+						} else {
+							newErr = new SQLNonTransientConnectionException(singleError, "08000");
+						}
+						if (ret == null) {
+							ret = newErr;
+						} else {
+							ret.setNextException(newErr);
+						}
+					}
+					throw ret;
+				}
+			} catch (SocketTimeoutException e) {
+				this.close(); // JDBC 4.1 semantics, abort()
+				throw new SQLNonTransientConnectionException("connection timed out", "08M33");
+			} catch (IOException e) {
+				closed = true;
+				throw new SQLNonTransientConnectionException(e.getMessage() + " (mserver5 still alive?)", "08006");
+			}
+		}
+	}
 }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDataSource.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDataSource.java
@@ -34,11 +34,11 @@ public class MonetDataSource extends Mon
 
 	private String user;
 	private String password; // insecure, but how to do it better?
-    private String description = "MonetDB database";
+	private String description = "MonetDB database";
 	private String url = "jdbc:monetdb://localhost/";
-    private int loginTimeout;
-    private String directory;
-    private final MonetDriver driver = new MonetDriver();
+	private int loginTimeout;
+	private String directory;
+	private final MonetDriver driver = new MonetDriver();
 
 	// the following properties are also standard:
 	// private String dataSourceName;
@@ -46,7 +46,7 @@ public class MonetDataSource extends Mon
 	// private String serverName;
 	// private String role;
 
-    public MonetDataSource() {}
+	public MonetDataSource() {}
 
 	/**
 	 * Attempts to establish a connection with the data source that this DataSource object represents.
@@ -72,13 +72,13 @@ public class MonetDataSource extends Mon
 		Properties props = new Properties();
 		props.put("user", username);
 		props.put("password", password);
-        if (loginTimeout > 0) {
-            props.put("so_timeout", Integer.toString(loginTimeout));
-        }
+		if (loginTimeout > 0) {
+			props.put("so_timeout", Integer.toString(loginTimeout));
+		}
 		if(directory != null) {
-            props.put("embedded", "true");
+			props.put("embedded", "true");
 			props.put("directory", directory);
-        }
+		}
 		return driver.connect(url, props);
 	}
 
@@ -184,34 +184,34 @@ public class MonetDataSource extends Mon
 		this.description = description;
 	}
 
-    /**
-     * Gets the directory value
-     *
-     * @return the directory value
-     */
-    public String getDirectory() {
-        return directory;
-    }
+	/**
+	 * Gets the directory value
+	 *
+	 * @return the directory value
+	 */
+	public String getDirectory() {
+		return directory;
+	}
 
-    /**
-     * Sets the directory value, meaning it wil start an embedded connection
-     *
-     * @param directory The directory location
-     */
-    public void setDirectory(String directory) {
-        this.directory = directory;
-    }
+	/**
+	 * Sets the directory value, meaning it wil start an embedded connection
+	 *
+	 * @param directory The directory location
+	 */
+	public void setDirectory(String directory) {
+		this.directory = directory;
+	}
 
-    /**
-     * Gets the embedded connection directory. If not, then a MAPI connection will be created instead.
-     *
-     * @return If the connection will be embedded. If not, then a MAPI connection will be created instead.
-     */
-    public boolean isEmbedded() {
-        return directory != null;
-    }
+	/**
+	 * Gets the embedded connection directory. If not, then a MAPI connection will be created instead.
+	 *
+	 * @return If the connection will be embedded. If not, then a MAPI connection will be created instead.
+	 */
+	public boolean isEmbedded() {
+		return directory != null;
+	}
 
-    /**
+	/**
 	 * Return the parent Logger of all the Loggers used by this data
 	 * source.  This should be the Logger farthest from the root Logger
 	 * that is still an ancestor of all of the Loggers used by this data
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
@@ -46,7 +46,7 @@ public class MonetDatabaseMetaData exten
 		try {
 			st = con.createStatement();
 			rs = st.executeQuery(
-				"SELECT \"name\", \"value\" FROM \"sys\".\"environment\"" +
+				"SELECT \"name\", \"value\" FROM \"sys\".\"env\"()" +
 				" WHERE \"name\" IN ('monet_version', 'max_clients')" +
 				" UNION SELECT 'current_user' as \"name\", current_user as \"value\"");
 			if (rs != null) {
@@ -2195,7 +2195,7 @@ public class MonetDatabaseMetaData exten
 			"cast(null AS varchar(1)) AS \"SCOPE_CATALOG\", " +
 			"cast(null AS varchar(1)) AS \"SCOPE_SCHEMA\", " +
 			"cast(null AS varchar(1)) AS \"SCOPE_TABLE\", " +
-			"cast(").append(MonetDriver.getJavaType("other")).append(" AS smallint) AS \"SOURCE_DATA_TYPE\", " +
+			"cast(null AS smallint) AS \"SOURCE_DATA_TYPE\", " +
 			"cast(CASE WHEN \"columns\".\"default\" IS NOT NULL AND \"columns\".\"default\" LIKE 'next value for %' THEN 'YES' ELSE 'NO' END AS varchar(3)) AS \"IS_AUTOINCREMENT\", " +
 			"cast('NO' AS varchar(3)) AS \"IS_GENERATEDCOLUMN\" " +
 		"FROM \"sys\".\"columns\", " +
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in
@@ -15,6 +15,7 @@ import nl.cwi.monetdb.mcl.protocol.Proto
 
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
+import java.net.SocketException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.sql.Connection;
@@ -23,6 +24,7 @@ import java.sql.DriverManager;
 import java.sql.DriverPropertyInfo;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLNonTransientConnectionException;
 import java.sql.Types;
 import java.util.*;
 import java.util.Map.Entry;
@@ -91,6 +93,7 @@ public final class MonetDriver implement
 	 * @param url the URL of the database
 	 * @return true if this driver understands the given URL; false otherwise
 	 */
+	@Override
 	public boolean acceptsURL(String url) {
 		return url != null && url.startsWith(MONETURL);
 	}
@@ -100,6 +103,7 @@ public final class MonetDriver implement
 	 *
 	 * @return this driver's major version number
 	 */
+	@Override
 	public int getMajorVersion() {
 		return DRIVERMAJOR;
 	}
@@ -109,6 +113,7 @@ public final class MonetDriver implement
 	 *
 	 * @return this driver's minor version number
 	 */
+	@Override
 	public int getMinorVersion() {
 		return DRIVERMINOR;
 	}
@@ -128,6 +133,7 @@ public final class MonetDriver implement
 	 * @return an array of DriverPropertyInfo objects describing possible properties. This array may be an empty array
 	 * if no properties are required.
 	 */
+	@Override
 	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
 		if (!acceptsURL(url))
 			return null;
@@ -196,6 +202,7 @@ public final class MonetDriver implement
 	 *
 	 * @return true if this driver is JDBC Compliant; false otherwise
 	 */
+	@Override
 	public boolean jdbcCompliant() {
 		return MONETJDBCCOMPLIANT;
 	}
@@ -302,16 +309,17 @@ public final class MonetDriver implement
 	}
 
 	/**
-	 * Return the parent Logger of all the Loggers used by this data
-	 * source.  This should be the Logger farthest from the root Logger
-	 * that is still an ancestor of all of the Loggers used by this data
-	 * source.  Configuring this Logger will affect all of the log
-	 * messages generated by the data source. In the worst case, this
-	 * may be the root Logger.
+	 * Return the parent Logger of all the Loggers used by this data source.
+	 * This should be the Logger farthest from the root Logger that is
+	 * still an ancestor of all of the Loggers used by this data source.
+	 * Configuring this Logger will affect all of the log messages
+	 * generated by the data source. In the worst case, this may be the root Logger.
 	 *
 	 * @return the parent Logger for this data source
 	 * @throws SQLFeatureNotSupportedException if the data source does not use java.util.logging
+	 * @since 1.7
 	 */
+	@Override
 	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
 		throw new SQLFeatureNotSupportedException("java.util.logging not in use", "0A000");
 	}
@@ -331,9 +339,8 @@ public final class MonetDriver implement
 	 * "password" properties should be included in the Properties object.
 	 *
 	 * @param url the URL of the database to which to connect
-	 * @param info a list of arbitrary string tag/value pairs as connection
-	 *        arguments. Normally at least a "user" and "password" property
-	 *        should be included
+	 * @param info a list of arbitrary string tag/value pairs as connection  arguments. Normally at least a "user" and
+	 * "password" property  should be included
 	 * @return a Connection object that represents a connection to the URL
 	 * @throws SQLException if a database access error occurs
 	 */
@@ -415,7 +422,7 @@ public final class MonetDriver implement
 				if(embeddedConnectionClass == null) {
 					embeddedConnectionClass = Class.forName("nl.cwi.monetdb.embedded.jdbc.EmbeddedConnection");
 					if(embeddedConnectionClass == null) { //if it is still null then there is a problem!
-						throw new SQLException("EmbeddedConnection Class not found! Please add monetdb-java-lite jar to the CLASSPATH");
+						throw new SQLNonTransientConnectionException("EmbeddedConnection Class not found! Please add monetdb-java-lite jar to the CLASSPATH");
 					}
 				}
 				res = (MonetConnection) embeddedConnectionClass
@@ -423,7 +430,7 @@ public final class MonetDriver implement
 					.newInstance(props, hash, language, directory);
 			} catch (InvocationTargetException | InstantiationException | IllegalAccessException |
 					 NoSuchMethodException | ClassNotFoundException e) {
-				throw new SQLException(e);
+				throw new SQLNonTransientConnectionException(e);
 			}
 		} else {
 			String hostname = props.getProperty("host");
@@ -468,11 +475,7 @@ public final class MonetDriver implement
 				sockTimeout = 0;
 				props.setProperty("so_timeout", "0");
 			}
-			try {
-				res = new MapiConnection(props, hash, language, blobIsBinary, clobIsLongChar, hostname, port, database);
-			} catch (IOException e) {
-				throw new SQLException(e);
-			}
+			res = new MapiConnection(props, hash, language, blobIsBinary, clobIsLongChar, hostname, port, database);
 			if(failedparse1) {
 				res.addWarning("Unable to parse port number from: " + port, "M1M05");
 			}
@@ -485,7 +488,11 @@ public final class MonetDriver implement
 			if(negative2) {
 				res.addWarning("Negative socket timeout not allowed. Value ignored", "M1M05");
 			}
-			res.setSoTimeout(sockTimeout);
+			try {
+				res.setSoTimeout(sockTimeout);
+			} catch(SocketException ex) {
+			    res.addWarning("Failed to set socket timeout: " + ex.getMessage(), "M1M05");
+			}
 		}
 
 		try { //attempt to connect and authenticate the user
@@ -505,15 +512,15 @@ public final class MonetDriver implement
 				throw new SQLException("Unable to connect (" + con.getHostname() + ":"
 						+ con.getPort() + "): " + e.getMessage(), "08006");
 			} else {
-				throw new SQLException("Unable to connect: " + e.getMessage(), "08006");
+				throw new SQLNonTransientConnectionException("Unable to connect: " + e.getMessage(), "08006");
 			}
 		} catch (ProtocolException e) {
-			throw new SQLException(e.getMessage(), "08001");
+			throw new SQLNonTransientConnectionException(e.getMessage(), "08001");
 		} catch (MCLException e) {
 			String[] connex = e.getMessage().split("\n");
-			SQLException sqle = new SQLException(connex[0], "08001", e);
+			SQLException sqle = new SQLNonTransientConnectionException(connex[0], "08001", e);
 			for (int i = 1; i < connex.length; i++) {
-				sqle.setNextException(new SQLException(connex[1], "08001"));
+				sqle.setNextException(new SQLNonTransientConnectionException(connex[1], "08001"));
 			}
 			throw sqle;
 		}
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
@@ -46,9 +46,9 @@ import java.util.Map;
  * </pre>
  *
  * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira
- * @version 0.4
+ * @version 0.5v
  */
-public class MonetPreparedStatement extends MonetStatement implements PreparedStatement {
+public class MonetPreparedStatement extends MonetStatement implements PreparedStatement, AutoCloseable {
 
 	private final MonetConnection connection;
 	private final String[] monetdbType;
@@ -106,18 +106,30 @@ public class MonetPreparedStatement exte
 
 		// fill the arrays
 		ResultSet rs = super.getResultSet();
-		for (int i = 0; rs.next(); i++) {
-			monetdbType[i] = rs.getString("type");
-			javaType[i] = MonetDriver.getJavaType(monetdbType[i]);
-			digits[i] = rs.getInt("digits");
-			scale[i] = rs.getInt("scale");
-			if (rscolcnt == 3)
-				continue;
-			schema[i] = rs.getString("schema");
-			table[i] = rs.getString("table");
-			column[i] = rs.getString("column");
+		if (rs != null) {
+			// System.out.println("After super.getResultSet();");
+			int type_colnr = rs.findColumn("type");
+			int digits_colnr = rs.findColumn("digits");
+			int scale_colnr = rs.findColumn("scale");
+			int schema_colnr = rs.findColumn("schema");
+			int table_colnr = rs.findColumn("table");
+			int column_colnr = rs.findColumn("column");
+			for (int i = 0; rs.next(); i++) {
+				monetdbType[i] = rs.getString(type_colnr);
+				javaType[i] = MonetDriver.getJavaType(monetdbType[i]);
+				digits[i] = rs.getInt(digits_colnr);
+				scale[i] = rs.getInt(scale_colnr);
+				if (rscolcnt == 3)
+					continue;
+				schema[i] = rs.getString(schema_colnr);
+				table[i] = rs.getString(table_colnr);
+				column[i] = rs.getString(column_colnr);
+				/* when column[i] != null it is a result column of the prepared query, see getColumnIdx(int),
+				   when column[i] == null it is a parameter for the prepared statement, see getParamIdx(int). */
+				// System.out.println("column " + i + " has value: " + column[i]);
+			}
+			rs.close();
 		}
-		rs.close();
 
 		// PreparedStatements are by default poolable
 		poolable = true;
@@ -238,6 +250,7 @@ public class MonetPreparedStatement exte
 	private int getColumnIdx(int colnr) throws SQLException {
 		int curcol = 0;
 		for (int i = 0; i < size; i++) {
+			/* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */
 			if (column[i] == null)
 				continue;
 			curcol++;
@@ -254,6 +267,7 @@ public class MonetPreparedStatement exte
 	private int getParamIdx(int paramnr) throws SQLException {
 		int curparam = 0;
 		for (int i = 0; i < size; i++) {
+			/* when column[i] == null it is a parameter, when column[i] != null it is a result column of the prepared query */
 			if (column[i] != null)
 				continue;
 			curparam++;
@@ -800,13 +814,13 @@ public class MonetPreparedStatement exte
 	 * Sets the designated parameter to the given Array object.  The
 	 * driver converts this to an SQL ARRAY value when it sends it to
 	 * the database.
-     *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 *
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x an Array object that maps an SQL ARRAY value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setArray(int i, Array x) throws SQLException {
+	public void setArray(int parameterIndex, Array x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setArray");
 	}
 
@@ -882,14 +896,14 @@ public class MonetPreparedStatement exte
 	 * The driver converts this to an SQL NUMERIC value when it sends it to the
 	 * database.
 	 *
-	 * @param idx the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setBigDecimal(int idx, BigDecimal x) throws SQLException {
+	public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
 		// get array position
-		int i = getParamIdx(idx);
+		int i = getParamIdx(parameterIndex);
 
 		// round to the scale of the DB:
 		x = x.setScale(scale[i], RoundingMode.HALF_UP);
@@ -910,7 +924,7 @@ public class MonetPreparedStatement exte
 			xStr = xStr.substring(0, Math.min(xStr.length(), dot + 1 + scale[i]));
 		while (xStr.startsWith("0") && xStr.length() > 1)
 			xStr = xStr.substring(1);
-		setValue(idx, xStr);
+		setValue(parameterIndex, xStr);
 	}
 
 	/**
@@ -983,12 +997,12 @@ public class MonetPreparedStatement exte
 	 * converts this to an SQL BLOB value when it sends it to the database.
 	 *
 	 * @param parameterIndex the first parameter is 1, the second is 2, ...
-	 * @param stream an object that contains the data to set the parameter value to
+	 * @param x a Blob object that maps an SQL BLOB value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setBlob(int parameterIndex, InputStream stream) throws SQLException {
-		if (stream == null) {
+	public void setBlob(int parameterIndex, InputStream x) throws SQLException {
+		if (x == null) {
 			setNull(parameterIndex, -1);
 			return;
 		}
@@ -997,7 +1011,7 @@ public class MonetPreparedStatement exte
 		ByteArrayOutputStream buf = new ByteArrayOutputStream();
 		int numChars;
 		try {
-			while ((numChars = stream.read(arr, 0, arr.length)) > 0) {
+			while ((numChars = x.read(arr, 0, arr.length)) > 0) {
 				buf.write(arr, 0, numChars);
 			}
 			setBytes(parameterIndex, buf.toByteArray());
@@ -1035,13 +1049,13 @@ public class MonetPreparedStatement exte
 	 * should be sent to the server as a LONGVARBINARY or a BLOB.
 	 *
 	 * @param parameterIndex the first parameter is 1, the second is 2, ...
-	 * @param stream an object that contains the data to set the parameter value to
+	 * @param is an object that contains the data to set the parameter value to
 	 * @param length the number of bytes in the parameter data
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setBlob(int parameterIndex, InputStream stream, long length) throws SQLException {
-		if (stream == null) {
+	public void setBlob(int parameterIndex, InputStream is, long length) throws SQLException {
+		if (is == null) {
 			setNull(parameterIndex, -1);
 			return;
 		}
@@ -1049,7 +1063,7 @@ public class MonetPreparedStatement exte
 			byte[] arr = new byte[(int) length];
 			ByteArrayOutputStream buf = new ByteArrayOutputStream((int) length);
 
-			int numChars = stream.read(arr, 0, (int) length);
+			int numChars = is.read(arr, 0, (int) length);
 			buf.write(arr, 0, numChars);
 			setBytes(parameterIndex, buf.toByteArray());
 		} catch (IOException e) {
@@ -1187,36 +1201,36 @@ public class MonetPreparedStatement exte
 	 * Sets the designated parameter to the given Clob object. The driver
 	 * converts this to an SQL CLOB value when it sends it to the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x a Clob object that maps an SQL CLOB value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setClob(int i, Clob x) throws SQLException {
+	public void setClob(int parameterIndex, Clob x) throws SQLException {
 		if (x == null) {
-			setNull(i, -1);
+			setNull(parameterIndex, -1);
 			return;
 		}
 
 		// simply serialise the CLOB into a variable for now... far from
 		// efficient, but might work for a few cases...
 		// be on your marks: we have to cast the length down!
-		setString(i, x.getSubString(1L, (int)(x.length())));
+		setString(parameterIndex, x.getSubString(1L, (int)(x.length())));
 	}
 
 	/**
 	 * Sets the designated parameter to the given Clob object. The driver
 	 * converts this to an SQL CLOB value when it sends it to the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param reader an object that contains the data to set the parameter
 	 *          value to
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setClob(int i, Reader reader) throws SQLException {
+	public void setClob(int parameterIndex, Reader reader) throws SQLException {
 		if (reader == null) {
-			setNull(i, -1);
+			setNull(parameterIndex, -1);
 			return;
 		}
 		// Some buffer. Size of 8192 is default for BufferedReader, so...
@@ -1227,7 +1241,7 @@ public class MonetPreparedStatement exte
 			while ((numChars = reader.read(arr, 0, arr.length)) > 0) {
 				buf.append(arr, 0, numChars);
 			}
-			setString(i, buf.toString());
+			setString(parameterIndex, buf.toString());
 		} catch (IOException e) {
 			throw new SQLException(e);
 		}
@@ -1244,16 +1258,16 @@ public class MonetPreparedStatement exte
 	 * extra work to determine whether the parameter data should be sent
 	 * to the server as a LONGVARCHAR or a CLOB.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param reader An object that contains the data to set the
 	 *        parameter value to.
 	 * @param length the number of characters in the parameter data.
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setClob(int i, Reader reader, long length) throws SQLException {
+	public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
 		if (reader == null || length < 0) {
-			setNull(i, -1);
+			setNull(parameterIndex, -1);
 			return;
 		}
 		// simply serialise the CLOB into a variable for now... far from
@@ -1267,7 +1281,7 @@ public class MonetPreparedStatement exte
 		}
 		// We have to rewind the buffer, because otherwise toString() returns "".
 		buf.rewind();
-		setString(i, buf.toString());
+		setString(parameterIndex, buf.toString());
 	}
 
 	/**
@@ -1371,15 +1385,15 @@ public class MonetPreparedStatement exte
 	 * necessary conversion from Java character format to the national
 	 * character set in the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param value the parameter value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setNCharacterStream(int i, Reader value) throws SQLException {
-		throw newSQLFeatureNotSupportedException("setNCharacterStream");
+	public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+		setCharacterStream(parameterIndex, value, 0);
 	}
 
 	/**
@@ -1388,7 +1402,7 @@ public class MonetPreparedStatement exte
 	 * necessary conversion from Java character format to the national
 	 * character set in the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param value the parameter value
 	 * @param length the number of characters in the parameter data.
 	 * @throws SQLException if a database access error occurs
@@ -1396,8 +1410,8 @@ public class MonetPreparedStatement exte
 	 *         not support this method
 	 */
 	@Override
-	public void setNCharacterStream(int i, Reader value, long length) throws SQLException {
-		throw newSQLFeatureNotSupportedException("setNCharacterStream");
+	public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
+		setCharacterStream(parameterIndex, value, length);
 	}
 
 	/**
@@ -1405,14 +1419,14 @@ public class MonetPreparedStatement exte
 	 * driver converts this to a SQL NCLOB value when it sends it to the
 	 * database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param value the parameter value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setNClob(int i, Reader value) throws SQLException {
+	public void setNClob(int parameterIndex, Reader value) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setNClob");
 	}
 
@@ -1421,14 +1435,14 @@ public class MonetPreparedStatement exte
 	 * driver converts this to a SQL NCLOB value when it sends it to the
 	 * database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param value the parameter value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setNClob(int i, NClob value) throws SQLException {
+	public void setNClob(int parameterIndex, NClob value) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setNClob");
 	}
 
@@ -1443,7 +1457,7 @@ public class MonetPreparedStatement exte
 	 * extra work to determine whether the parameter data should be sent
 	 * to the server as a LONGNVARCHAR or a NCLOB.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param r An object that contains the data to set the parameter
 	 *          value to
 	 * @param length the number of characters in the parameter data
@@ -1452,7 +1466,7 @@ public class MonetPreparedStatement exte
 	 *         not support this method
 	 */
 	@Override
-	public void setNClob(int i, Reader r, long length) throws SQLException {
+	public void setNClob(int parameterIndex, Reader r, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setNClob");
 	}
 
@@ -1462,15 +1476,15 @@ public class MonetPreparedStatement exte
 	 * value (depending on the argument's size relative to the driver's
 	 * limits on NVARCHAR values) when it sends it to the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param value the parameter value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setNString(int i, String value) throws SQLException {
-		throw newSQLFeatureNotSupportedException("setNString");
+	public void setNString(int parameterIndex, String value) throws SQLException {
+		setString(parameterIndex, value);
 	}
 
 	/**
@@ -1505,7 +1519,7 @@ public class MonetPreparedStatement exte
 	 * parameter of any JDBC type. If the parameter does not have a
 	 * user-defined or REF type, the given typeName is ignored.
 	 *
-	 * @param paramIndex the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param sqlType a value from java.sql.Types
 	 * @param typeName the fully-qualified name of an SQL user-defined type;
 	 *                 ignored if the parameter is not a user-defined type or
@@ -1513,9 +1527,9 @@ public class MonetPreparedStatement exte
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException {
+	public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
 		// MonetDB/SQL's NULL needs no type
-		setNull(paramIndex, sqlType);
+		setNull(parameterIndex, sqlType);
 	}
 
 	/**
@@ -1540,14 +1554,14 @@ public class MonetPreparedStatement exte
 	 * example, if the object is of a class implementing more than one
 	 * of the interfaces named above.
 	 *
-	 * @param index the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the object containing the input parameter value
 	 * @throws SQLException if a database access error occurs or the type of
 	 *                      the given object is ambiguous
 	 */
 	@Override
-	public void setObject(int index, Object x) throws SQLException {
-		setObject(index, x, javaType[getParamIdx(index)]);
+	public void setObject(int parameterIndex, Object x) throws SQLException {
+		setObject(parameterIndex, x, javaType[getParamIdx(parameterIndex)], 0);
 	}
 
 	/**
@@ -1600,127 +1614,14 @@ public class MonetPreparedStatement exte
 	 * @see Types
 	 */
 	@Override
-	public void setObject(
-			int parameterIndex,
-			Object x,
-			int targetSqlType,
-			int scale)
-			throws SQLException
-	{
+	public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException {
+		if (x == null) {
+			setNull(parameterIndex, -1);
+			return;
+		}
 		// this is according to table B-5
 		if (x instanceof String) {
-			switch (targetSqlType) {
-				case Types.CHAR:
-				case Types.VARCHAR:
-				case Types.LONGVARCHAR:
-				case Types.CLOB:
-					setString(parameterIndex, (String)x);
-					break;
-				case Types.TINYINT:
-				case Types.SMALLINT:
-				case Types.INTEGER:
-				{
-					int val;
-					try {
-						val = Integer.parseInt((String)x);
-					} catch (NumberFormatException e) {
-						val = 0;
-					}
-					setInt(parameterIndex, val);
-				} break;
-				case Types.BIGINT:
-				{
-					long val;
-					try {
-						val = Long.parseLong((String)x);
-					} catch (NumberFormatException e) {
-						val = 0;
-					}
-					setLong(parameterIndex, val);
-				} break;
-				case Types.REAL:
-				{
-					float val;
-					try {
-						val = Float.parseFloat((String)x);
-					} catch (NumberFormatException e) {
-						val = 0;
-					}
-					setFloat(parameterIndex, val);
-				} break;
-				case Types.FLOAT:
-				case Types.DOUBLE:
-				{
-					double val;
-					try {
-						val = Double.parseDouble((String)x);
-					} catch (NumberFormatException e) {
-						val = 0;
-					}
-					setDouble(parameterIndex, val);
-				} break;
-				case Types.DECIMAL:
-				case Types.NUMERIC:
-				{
-					BigDecimal val;
-					try {
-						val = new BigDecimal((String)x);
-					} catch (NumberFormatException e) {
-						try {
-							val = new BigDecimal(0.0);
-						} catch (NumberFormatException ex) {
-							throw new SQLException("Internal error: unable to create template BigDecimal: " + ex.getMessage(), "M0M03");
-						}
-					}
-					val = val.setScale(scale, BigDecimal.ROUND_HALF_UP);
-					setBigDecimal(parameterIndex, val);
-				} break;
-				case Types.BIT:
-				case Types.BOOLEAN:
-					setBoolean(parameterIndex, (Boolean.valueOf((String)x)).booleanValue());
-					break;
-				case Types.BINARY:
-				case Types.VARBINARY:
-				case Types.LONGVARBINARY:
-					setBytes(parameterIndex, ((String)x).getBytes());
-					break;
-				case Types.DATE:
-				{
-					java.sql.Date val;
-					try {
-						val = java.sql.Date.valueOf((String)x);
-					} catch (IllegalArgumentException e) {
-						val = new java.sql.Date(0L);
-					}
-					setDate(parameterIndex, val);
-				} break;
-				case Types.TIME:
-				{
-					Time val;
-					try {
-						val = Time.valueOf((String)x);
-					} catch (IllegalArgumentException e) {
-						val = new Time(0L);
-					}
-					setTime(parameterIndex, val);
-				} break;
-				case Types.TIMESTAMP:
-				{
-					Timestamp val;
-					try {
-						val = Timestamp.valueOf((String)x);
-					} catch (IllegalArgumentException e) {
-						val = new Timestamp(0L);
-					}
-					setTimestamp(parameterIndex, val);
-				} break;
-				case Types.NCHAR:
-				case Types.NVARCHAR:
-				case Types.LONGNVARCHAR:
-					throw newSQLFeatureNotSupportedException("setObject() with targetType N[VAR]CHAR");
-				default:
-					throw new SQLException("Conversion not allowed", "M1M05");
-			}
+			setString(parameterIndex, (String)x);
 		} else if (x instanceof BigDecimal ||
 				x instanceof Byte ||
 				x instanceof Short ||
@@ -1879,13 +1780,13 @@ public class MonetPreparedStatement exte
 						setDate(parameterIndex, new java.sql.Date(
 								((java.util.Date)x).getTime()));
 					} else if (x instanceof Calendar) {
-						setDate(parameterIndex, new java.sql.Date(
-								((Calendar)x).getTimeInMillis()));
+						setDate(parameterIndex, new java.sql.Date(((Calendar)x).getTimeInMillis()));
 					} else {
 						throw new SQLException("Conversion not allowed", "M1M05");
 					}
 					break;
 				case Types.TIME:
+				case 2013: //Types.TIME_WITH_TIMEZONE:
 					if (x instanceof Time) {
 						setTime(parameterIndex, (Time)x);
 					} else if (x instanceof Timestamp) {
@@ -1894,13 +1795,13 @@ public class MonetPreparedStatement exte
 						setTime(parameterIndex, new java.sql.Time(
 								((java.util.Date)x).getTime()));
 					} else if (x instanceof Calendar) {
-						setTime(parameterIndex, new java.sql.Time(
-								((Calendar)x).getTimeInMillis()));
+						setTime(parameterIndex, new java.sql.Time(((Calendar)x).getTimeInMillis()));
 					} else {
 						throw new SQLException("Conversion not allowed", "M1M05");
 					}
 					break;
 				case Types.TIMESTAMP:
+				case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 					if (x instanceof Timestamp) {
 						setTimestamp(parameterIndex, (Timestamp)x);
 					} else if (x instanceof java.sql.Date) {
@@ -1909,8 +1810,7 @@ public class MonetPreparedStatement exte
 						setTimestamp(parameterIndex, new java.sql.Timestamp(
 								((java.util.Date)x).getTime()));
 					} else if (x instanceof Calendar) {
-						setTimestamp(parameterIndex, new java.sql.Timestamp(
-								((Calendar)x).getTimeInMillis()));
+						setTimestamp(parameterIndex, new java.sql.Timestamp(((Calendar)x).getTimeInMillis()));
 					} else {
 						throw new SQLException("Conversion not allowed", "M1M05");
 					}
@@ -1926,9 +1826,9 @@ public class MonetPreparedStatement exte
 			}
 		} else if (x instanceof Array) {
 			setArray(parameterIndex, (Array)x);
-		} else if (x instanceof Blob) {
+		} else if (x instanceof Blob || x instanceof MonetBlob) {
 			setBlob(parameterIndex, (Blob)x);
-		} else if (x instanceof Clob) {
+		} else if (x instanceof Clob || x instanceof MonetClob) {
 			setClob(parameterIndex, (Clob)x);
 		} else if (x instanceof Struct) {
 			// I have no idea how to do this...
@@ -1937,12 +1837,14 @@ public class MonetPreparedStatement exte
 			setRef(parameterIndex, (Ref)x);
 		} else if (x instanceof java.net.URL) {
 			setURL(parameterIndex, (java.net.URL)x);
+		} else if (x instanceof java.util.UUID) {
+			setString(parameterIndex, x.toString());
 		} else if (x instanceof RowId) {
 			setRowId(parameterIndex, (RowId)x);
 		} else if (x instanceof NClob) {
-			throw newSQLFeatureNotSupportedException("setObject() with object of type NClob");
+			setNClob(parameterIndex, (NClob)x);
 		} else if (x instanceof SQLXML) {
-			throw newSQLFeatureNotSupportedException("setObject() with object of type SQLXML");
+			setSQLXML(parameterIndex, (SQLXML)x);
 		} else if (x instanceof SQLData) { // not in JDBC4.1???
 			SQLData sx = (SQLData)x;
 			final int paramnr = parameterIndex;
@@ -2022,7 +1924,7 @@ public class MonetPreparedStatement exte
 
 				@Override
 				public void writeCharacterStream(Reader x) throws SQLException {
-					setCharacterStream(paramnr, x);
+					setCharacterStream(paramnr, x, 0);
 				}
 
 				@Override
@@ -2092,7 +1994,7 @@ public class MonetPreparedStatement exte
 			};
 			sx.writeSQL(out);
 		} else {	// java Class
-			throw newSQLFeatureNotSupportedException("setObject() with object of type Class");
+			throw newSQLFeatureNotSupportedException("setObject() with object of type Class " + x.getClass().getName());
 		}
 	}
 
@@ -2101,14 +2003,14 @@ public class MonetPreparedStatement exte
 	 * The driver converts this to an SQL REF value when it sends it to the
 	 * database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x an SQL REF value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setRef(int i, Ref x) throws SQLException {
+	public void setRef(int parameterIndex, Ref x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setRef");
 	}
 
@@ -2117,14 +2019,14 @@ public class MonetPreparedStatement exte
 	 * The driver converts this to a SQL ROWID value when it sends it to
 	 * the database.
 	 *
-	 * @param i the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public void setRowId(int i, RowId x) throws SQLException {
+	public void setRowId(int parameterIndex, RowId x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("setRowId");
 	}
 
@@ -2157,7 +2059,164 @@ public class MonetPreparedStatement exte
 			setNull(parameterIndex, -1);
 			return;
 		}
-		setValue(parameterIndex, "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'");
+		int paramIdx = getParamIdx(parameterIndex);	// this will throw a SQLException if parameter can not be found
+
+		/* depending on the parameter data type (as expected by MonetDB) we
+		   may need to add the data type as cast prefix to the parameter value */
+		int paramJdbcType = javaType[paramIdx];
+		String paramMonetdbType = monetdbType[paramIdx];
+
+		switch (paramJdbcType) {
+			case Types.CHAR:
+			case Types.VARCHAR:
+			case Types.LONGVARCHAR:
+			case Types.CLOB:
+			case Types.NCHAR:
+			case Types.NVARCHAR:
+			case Types.LONGNVARCHAR:
+			{
+				String castprefix = "";
+				switch (paramMonetdbType) {
+					// some MonetDB specific data types require a cast prefix
+					case "inet":
+						try {
+							// check if x represents a valid inet string to prevent
+							// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+							nl.cwi.monetdb.jdbc.MonetINET inet_obj = new nl.cwi.monetdb.jdbc.MonetINET(x);
+						} catch (Exception se) {
+							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + se.getMessage(), "22M29");
+						}
+						castprefix = "inet ";
+						break;
+					case "json":
+						// There is no support for JSON in standard java class libraries.
+						// Possibly we could use org.json.simple.JSONObject or other/faster libs
+						// javax.json.Json is not released yet (see https://json-processing-spec.java.net/)
+						// see also https://github.com/fabienrenaud/java-json-benchmark
+						// Note that it would make our JDBC driver dependent of an external jar
+						// and we don't want that.
+
+						// do simplistic check if x represents a valid json string to prevent
+						// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+						if (x.isEmpty() ||
+							(x.startsWith("{") && !x.endsWith("}")) ||
+							(x.startsWith("[") && !x.endsWith("]"))
+							// TODO check completely if x represents a valid json string
+						   )
+							throw new SQLDataException("Invalid json string. It does not start with { or [ and end with } or ]", "22M32");
+
+						// TODO check completely if x represents a valid json string
+
+						castprefix = "json ";
+						break;
+					case "url":
+						try {
+							// also check if x represents a valid url string to prevent
+							// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+							java.net.URL url_obj = new java.net.URL(x);
+						} catch (java.net.MalformedURLException mue) {
+							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + mue.getMessage(), "22M30");
+						}
+						castprefix = "url ";
+						break;
+					case "uuid":
+						try {
+							// also check if x represents a valid uuid string to prevent
+							// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+							java.util.UUID uuid_obj = java.util.UUID.fromString(x);
+						} catch (IllegalArgumentException iae) {
+							throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + iae.getMessage(), "22M31");
+						}
+						castprefix = "uuid ";
+						break;
+				}
+				/* in specific cases prefix the string with: inet or json or url or uuid */
+				setValue(parameterIndex,
+					castprefix + "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'");
+				break;
+			}
+			case Types.TINYINT:
+			case Types.SMALLINT:
+			case Types.INTEGER:
+			case Types.BIGINT:
+			case Types.REAL:
+			case Types.FLOAT:
+			case Types.DOUBLE:
+			case Types.DECIMAL:
+			case Types.NUMERIC:
+				try {
+					// check (by calling parse) if the string represents a valid number to prevent
+					// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+					if (paramJdbcType == Types.TINYINT) {
+						int number = Byte.parseByte(x);
+					} else if (paramJdbcType == Types.SMALLINT ) {
+						int number = Short.parseShort(x);
+					} else if (paramJdbcType == Types.INTEGER) {
+						int number = Integer.parseInt(x);
+					} else if (paramJdbcType == Types.BIGINT) {
+						long number = Long.parseLong(x);
+					} else if (paramJdbcType == Types.REAL || paramJdbcType == Types.DOUBLE || paramJdbcType == Types.FLOAT) {
+						double number = Double.parseDouble(x);
+					} else {
+						BigDecimal number = new BigDecimal(x);
+					}
+				} catch (NumberFormatException nfe) {
+					throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + nfe.getMessage(), "22003");
+				}
+				setValue(parameterIndex, x);
+				break;
+			case Types.BIT:
+			case Types.BOOLEAN:
+				if  (x.equalsIgnoreCase("false") || x.equalsIgnoreCase("true") || x.equals("0") || x.equals("1")) {
+					setValue(parameterIndex, x);
+				} else {
+					throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed", "22000");
+				}
+				break;
+			case Types.DATE:
+			case Types.TIME:
+			case 2013: //Types.TIME_WITH_TIMEZONE:
+			case Types.TIMESTAMP:
+			case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
+				try {
+					// check if the string represents a valid calendar date or time or timestamp to prevent
+					// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+					if (paramJdbcType == Types.DATE) {
+						java.sql.Date datum = java.sql.Date.valueOf(x);
+					} else if (paramJdbcType == Types.TIME || paramJdbcType == 2013) {
+						Time tijdstip = Time.valueOf(x);
+					} else {
+						Timestamp tijdstip = Timestamp.valueOf(x);
+					}
+				} catch (IllegalArgumentException iae) {
+					throw new SQLDataException("Conversion of string: " + x + " to parameter data type " + paramMonetdbType + " failed. " + iae.getMessage(), "22007");
+				}
+				/* prefix the string with: date or time or timetz or timestamp or timestamptz */
+				setValue(parameterIndex, paramMonetdbType + " '" + x + "'");
+				break;
+			case Types.BINARY:
+			case Types.VARBINARY:
+			case Types.LONGVARBINARY:
+			case Types.BLOB:
+				// check if the string x contains pairs of hex chars to prevent
+				// failing exec #(..., ...) calls which destroy the prepared statement, see bug 6351
+				int xlen = x.length();
+				for (int i = 0; i < xlen; i++) {
+					char c = x.charAt(i);
+					if (c < '0' || c > '9') {
+						if (c < 'A' || c > 'F') {
+							if (c < 'a' || c > 'f') {
+								throw new SQLDataException("Invalid string for parameter data type " + paramMonetdbType + ". The string may contain only hex chars", "22M28");
+							}
+						}
+					}
+				}
+				/* prefix the string with: blob */
+				setValue(parameterIndex, "blob '" + x + "'");
+				break;
+			default:
+				throw new SQLException("Conversion of string to parameter data type " + paramMonetdbType + " is not (yet) supported", "M1M05");
+		}
 	}
 
 	/**
@@ -2181,13 +2240,13 @@ public class MonetPreparedStatement exte
 	 * The driver converts this to an SQL TIME value when it sends it to
 	 * the database.
 	 *
-	 * @param index the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setTime(int index, Time x) throws SQLException {
-		setTime(index, x, null);
+	public void setTime(int parameterIndex, Time x) throws SQLException {
+		setTime(parameterIndex, x, null);
 	}
 
 	/**
@@ -2200,34 +2259,35 @@ public class MonetPreparedStatement exte
 	 * timezone, which is that of the virtual machine running the
 	 * application.
 	 *
-	 * @param index the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @param cal the Calendar object the driver will use to construct the time
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setTime(int index, Time x, Calendar cal) throws SQLException {
+	public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
 		if (x == null) {
-			setNull(index, -1);
+			setNull(parameterIndex, -1);
 			return;
 		}
 
-		boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz");
+		String MonetDBType = monetdbType[getParamIdx(parameterIndex)];
+		boolean hasTimeZone = ("timetz".equals(MonetDBType) || "timestamptz".equals(MonetDBType));
 		if (hasTimeZone) {
 			// timezone shouldn't matter, since the server is timezone
 			// aware in this case
 			String RFC822 = mTimeZ.format(x);
-			setValue(index, "timetz '" + RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'");
+			setValue(parameterIndex, "timetz '" + RFC822.substring(0, 15) + ":" + RFC822.substring(15) + "'");
 		} else {
 			// server is not timezone aware for this field, and no
 			// calendar given, since we told the server our timezone at
 			// connection creation, we can just write a plain timestamp
 			// here
 			if (cal == null) {
-				setValue(index, "time '" + x.toString() + "'");
+				setValue(parameterIndex, "time '" + x.toString() + "'");
 			} else {
 				mTime.setTimeZone(cal.getTimeZone());
-				setValue(index, "time '" + mTime.format(x) + "'");
+				setValue(parameterIndex, "time '" + mTime.format(x) + "'");
 			}
 		}
 	}
@@ -2237,13 +2297,13 @@ public class MonetPreparedStatement exte
 	 * value.  The driver converts this to an SQL TIMESTAMP value when
 	 * it sends it to the database.
 	 *
-	 * @param index the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setTimestamp(int index, Timestamp x) throws SQLException {
-		setTimestamp(index, x, null);
+	public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
+		setTimestamp(parameterIndex, x, null);
 	}
 
 	/**
@@ -2256,35 +2316,35 @@ public class MonetPreparedStatement exte
 	 * default timezone, which is that of the virtual machine running
 	 * the application.
 	 *
-	 * @param index the first parameter is 1, the second is 2, ...
+	 * @param parameterIndex the first parameter is 1, the second is 2, ...
 	 * @param x the parameter value
 	 * @param cal the Calendar object the driver will use to construct the
 	 *            timestamp
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setTimestamp(int index, Timestamp x, Calendar cal) throws SQLException {
+	public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
 		if (x == null) {
-			setNull(index, -1);
+			setNull(parameterIndex, -1);
 			return;
 		}
 
-		boolean hasTimeZone = monetdbType[getParamIdx(index)].endsWith("tz");
+		String MonetDBType = monetdbType[getParamIdx(parameterIndex)];
+		boolean hasTimeZone = ("timestamptz".equals(MonetDBType) || "timetz".equals(MonetDBType));
 		if (hasTimeZone) {
 			// timezone shouldn't matter, since the server is timezone
 			// aware in this case
 			String RFC822 = mTimestampZ.format(x);
-			setValue(index, "timestamptz '" + RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'");
+			setValue(parameterIndex, "timestamptz '" + RFC822.substring(0, 26) + ":" + RFC822.substring(26) + "'");
 		} else {
 			// server is not timezone aware for this field, and no
 			// calendar given, since we told the server our timezone at
-			// connection creation, we can just write a plain timestamp
-			// here
+			// connection creation, we can just write a plain timestamp here
 			if (cal == null) {
-				setValue(index, "timestamp '" + x.toString() + "'");
+				setValue(parameterIndex, "timestamp '" + x.toString() + "'");
 			} else {
 				mTimestamp.setTimeZone(cal.getTimeZone());
-				setValue(index, "timestamp '" + mTimestamp.format(x) + "'");
+				setValue(parameterIndex, "timestamp '" + mTimestamp.format(x) + "'");
 			}
 		}
 	}
@@ -2326,8 +2386,14 @@ public class MonetPreparedStatement exte
 	 */
 	@Override
 	public void setURL(int parameterIndex, URL x) throws SQLException {
-		setString(parameterIndex, x.toString());
-		values[getParamIdx(parameterIndex)] = "url " + values[getParamIdx(parameterIndex)];
+		if (x == null) {
+			setNull(parameterIndex, -1);
+			return;
+		}
+
+		String val = x.toString();
+		setValue(parameterIndex, "url '" + val.replaceAll("\\\\", "\\\\\\\\")
+				.replaceAll("'", "\\\\'") + "'");
 	}
 
 	/**
@@ -2369,12 +2435,12 @@ public class MonetPreparedStatement exte
 	 * Sets the given index with the supplied value. If the given index is out of bounds, and SQLException is thrown.
 	 * The given value should never be null.
 	 *
-	 * @param index the parameter index
+	 * @param parameterIndex the parameter index
 	 * @param val the exact String representation to set
 	 * @throws SQLException if the given index is out of bounds
 	 */
-	private void setValue(int index, String val) throws SQLException {
-		values[getParamIdx(index)] = val;
+	private void setValue(int parameterIndex, String val) throws SQLException {
+		values[getParamIdx(parameterIndex)] = (val == null ? "NULL" : val);
 	}
 
 	/**
@@ -2388,9 +2454,7 @@ public class MonetPreparedStatement exte
 	 */
 	private String transform() throws SQLException {
 		StringBuilder buf = new StringBuilder(8 + 12 * size);
-		buf.append("exec ");
-		buf.append(id);
-		buf.append('(');
+		buf.append("exec ").append(id).append('(');
 		// check if all columns are set and do a replace
 		int col = 0;
 		for (int i = 0; i < size; i++) {
@@ -2399,8 +2463,8 @@ public class MonetPreparedStatement exte
 			col++;
 			if (col > 1)
 				buf.append(',');
-			if (values[i] == null) throw
-				new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05");
+			if (values[i] == null)
+				throw new SQLException("Cannot execute, parameter " + col + " is missing.", "M1M05");
 
 			buf.append(values[i]);
 		}
@@ -2411,19 +2475,20 @@ public class MonetPreparedStatement exte
 
 	/**
 	 * Small helper method that formats the "Invalid Parameter Index number ..." message
-	 * and creates a new SQLException object whose SQLState is set to "M1M05".
+	 * and creates a new SQLDataException object whose SQLState is set
+	 * to "22010": invalid indicator parameter value.
 	 *
 	 * @param paramIdx the parameter index number
-	 * @return a new created SQLException object with SQLState M1M05
+	 * @return a new created SQLDataException object with SQLState 22010
 	 */
-	private static SQLException newSQLInvalidParameterIndexException(int paramIdx) {
-		return new SQLException("Invalid Parameter Index number: " + paramIdx, "M1M05");
+	private static SQLDataException newSQLInvalidParameterIndexException(int paramIdx) {
+		return new SQLDataException("Invalid Parameter Index number: " + paramIdx, "22010");
 	}
 
 	/**
 	 * Small helper method that formats the "Method ... not implemented" message
 	 * and creates a new SQLFeatureNotSupportedException object
-	 * whose SQLState is set to "0A000".
+	 * whose SQLState is set to "0A000": feature not supported.
 	 *
 	 * @param name the method name
 	 * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
@@ -12,10 +12,7 @@ import nl.cwi.monetdb.mcl.protocol.Proto
 import nl.cwi.monetdb.mcl.responses.AbstractDataBlockResponse;
 import nl.cwi.monetdb.mcl.responses.ResultSetResponse;
 
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.Reader;
-import java.io.StringReader;
+import java.io.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
@@ -47,7 +44,7 @@ import java.util.UUID;
  * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira
  * @version 0.8
  */
-public class MonetResultSet extends MonetWrapper implements ResultSet {
+public class MonetResultSet extends MonetWrapper implements ResultSet, AutoCloseable {
 
 	/** The current position of the cursor for this ResultSet object */
 	int curRow = 0;
@@ -80,9 +77,9 @@ public class MonetResultSet extends Mone
 	 *
 	 * @param statement the statement which created this ResultSet
 	 * @param header a header containing the query, resultset type, etc.
-	 * @throws SQLException is a protocol error occurs
+	 * @throws IllegalArgumentException if called with null or invalid value for one of the arguments
 	 */
-	MonetResultSet(Statement statement, ResultSetResponse header) throws SQLException {
+	MonetResultSet(Statement statement, ResultSetResponse header) throws IllegalArgumentException {
 		if (statement == null) {
 			throw new IllegalArgumentException("Statement may not be null!");
 		}
@@ -111,7 +108,7 @@ public class MonetResultSet extends Mone
 	 * @param columns the column names
 	 * @param types the column types
 	 * @param results the number of rows in the ResultSet
-	 * @throws IllegalArgumentException if communicating with monet failed
+	 * @throws IllegalArgumentException if called with null or invalid value for one of the arguments
 	 */
 	MonetResultSet(Statement statement, String[] columns, String[] types, int[] JdbcSQLTypes, int results)
 			throws IllegalArgumentException {
@@ -144,14 +141,14 @@ public class MonetResultSet extends Mone
 	 * Moves the cursor to the given row number in this ResultSet object.
 	 *
 	 * If the row number is positive, the cursor moves to the given row number with respect to the beginning of the
-     * result set. The first row is row 1, the second is row 2, and so on.
+	 * result set. The first row is row 1, the second is row 2, and so on.
 	 *
 	 * If the given row number is negative, the cursor moves to an absolute row position with respect to the end of the
-     * result set. For example, calling the method absolute(-1) positions the cursor on the last row; calling the
+	 * result set. For example, calling the method absolute(-1) positions the cursor on the last row; calling the
 	 * method absolute(-2) moves the cursor to the next-to-last row, and so on.
 	 *
 	 * An attempt to position the cursor beyond the first/last row in the result set leaves the cursor before the first
-     * row or after the last row.
+	 * row or after the last row.
 	 * Note: calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as calling last().
 	 *
 	 * @param row the number of the row to which the cursor should move. A positive number indicates the row number
@@ -174,12 +171,11 @@ public class MonetResultSet extends Mone
 			row = tupleCount + row + 1;
 		}
 		// now place the row not farther than just before or after the result
-		if (row < 0) {
-			row = 0; // before first
-		} else if (row > tupleCount + 1) {
-			row = tupleCount + 1; // after last
-		}
-		// store it
+		if (row < 0)
+			row = 0;	// before first
+		else if (row > tupleCount + 1)
+			row = tupleCount + 1;	// after last
+
 		this.curRow = row;
 		this.currentBlock = header.getDataBlockCorrespondingToLine(row - 1);
 		return this.curRow <= this.tupleCount;
@@ -237,25 +233,25 @@ public class MonetResultSet extends Mone
 	 * case insensitive. If a select list contains the same column more than once, the first instance of the
 	 * column will be returned.
 	 *
-	 * @param columnName the name of the column
+	 * @param columnLabel the name of the column
 	 * @return the column index of the given column name
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public int findColumn(String columnName) throws SQLException {
-		if (columnName != null) {
+	public int findColumn(String columnLabel) throws SQLException {
+		if (columnLabel != null) {
 			final int array_size = columns.length;
 			for (int i = 0; i < array_size; i++) {
-				if (columnName.equals(columns[i]))
+				if (columnLabel.equals(columns[i]))
 					return i + 1;
 			}
 			/* if an exact match did not succeed try a case insensitive match */
 			for (int i = 0; i < array_size; i++) {
-				if (columnName.equalsIgnoreCase(columns[i]))
+				if (columnLabel.equalsIgnoreCase(columns[i]))
 					return i + 1;
 			}
 		}
-		throw new SQLException("No such column name: " + columnName, "M1M05");
+		throw new SQLException("No such column name: " + columnLabel, "M1M05");
 	}
 
 	/**
@@ -275,46 +271,46 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public Array getArray(String colName) throws SQLException {
+	public Array getArray(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getArray");
 	}
 
 	@Override
 	public InputStream getAsciiStream(int columnIndex) throws SQLException {
-        try {
+		try {
 			InputStream res = null;
-            switch (JdbcSQLTypes[columnIndex - 1]) {
-                case Types.CLOB:
+			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.CLOB:
 					Clob cl = getClob(columnIndex);
-                    if(cl != null) {
-                        res = cl.getAsciiStream();
-                    }
+					if(cl != null) {
+						res = cl.getAsciiStream();
+					}
 					break;
-                case Types.BLOB:
-                case Types.LONGVARBINARY:
-                case Types.CHAR:
-                case Types.VARCHAR:
-                case Types.LONGVARCHAR:
-                    byte[] bytes = getBytes(columnIndex);
-                    if(bytes != null) {
-                        res = new ByteArrayInputStream(getBytes(columnIndex));
-                    }
+				case Types.BLOB:
+				case Types.LONGVARBINARY:
+				case Types.CHAR:
+				case Types.VARCHAR:
+				case Types.LONGVARCHAR:
+					byte[] bytes = getBytes(columnIndex);
+					if(bytes != null) {
+						res = new ByteArrayInputStream(getBytes(columnIndex));
+					}
 					break;
-                default:
-                    throw new SQLException("Conversion from " + types[columnIndex - 1] +
-                            " to ascii stream not supported", "M1M05");
-            }
-            return res;
-        } catch (ClassCastException ex) {
-            throw new SQLException(ex.getMessage());
-        } catch (IndexOutOfBoundsException e) {
-            throw newSQLInvalidColumnIndexException(columnIndex);
-        }
+				default:
+					throw new SQLException("Conversion from " + types[columnIndex - 1] +
+							" to ascii stream not supported", "M1M05");
+			}
+			return res;
+		} catch (ClassCastException ex) {
+			throw new SQLException(ex.getMessage());
+		} catch (IndexOutOfBoundsException e) {
+			throw newSQLInvalidColumnIndexException(columnIndex);
+		}
 	}
 
 	@Override
-	public InputStream getAsciiStream(String columnName) throws SQLException {
-        return getAsciiStream(findColumn(columnName));
+	public InputStream getAsciiStream(String columnLabel) throws SQLException {
+		throw newSQLFeatureNotSupportedException("getAsciiStream");
 	}
 
 	@Override
@@ -325,73 +321,73 @@ public class MonetResultSet extends Mone
 
 	@Override
 	@Deprecated
-	public InputStream getUnicodeStream(String columnName) throws SQLException {
+	public InputStream getUnicodeStream(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getUnicodeStream");
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of
-     * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable
-     * for retrieving large LONGVARBINARY values.
+	 * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable
+	 * for retrieving large LONGVARBINARY values.
 	 * <br/><br/>
 	 * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next
-     * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method
-     * InputStream.available  is called whether there is data available or not.
+	 * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method
+	 * InputStream.available  is called whether there is data available or not.
 	 *
 	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the
-     * value is SQL NULL, the value returned is null
+	 * value is SQL NULL, the value returned is null
 	 * @throws SQLException if the columnIndex is not valid; if a database access error occurs or this method is called
-     * on a closed result set
+	 * on a closed result set
 	 */
 	@Override
 	public InputStream getBinaryStream(int columnIndex) throws SQLException {
-        try {
+		try {
 			InputStream res = null;
-            switch (JdbcSQLTypes[columnIndex - 1]) {
-                case Types.BLOB:
-                    Blob cl = getBlob(columnIndex);
-                    if(cl != null) {
-                        res = cl.getBinaryStream();
-                    }
-                    break;
-                case Types.LONGVARBINARY:
-                    byte[] bytes = getBytes(columnIndex);
-                    if(bytes != null) {
-                        res = new ByteArrayInputStream(getBytes(columnIndex));
-                    }
-                    break;
-                default:
-                    throw new SQLException("Conversion from " + types[columnIndex - 1] +
-                            " to binary stream not supported", "M1M05");
-            }
+			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.BLOB:
+					Blob cl = getBlob(columnIndex);
+					if(cl != null) {
+						res = cl.getBinaryStream();
+					}
+					break;
+				case Types.LONGVARBINARY:
+					byte[] bytes = getBytes(columnIndex);
+					if(bytes != null) {
+						res = new ByteArrayInputStream(getBytes(columnIndex));
+					}
+					break;
+				default:
+					throw new SQLException("Conversion from " + types[columnIndex - 1] +
+							" to binary stream not supported", "M1M05");
+			}
 			return res;
-        } catch (ClassCastException ex) {
-            throw new SQLException(ex.getMessage());
-        } catch (IndexOutOfBoundsException e) {
-            throw newSQLInvalidColumnIndexException(columnIndex);
-        }
+		} catch (ClassCastException ex) {
+			throw new SQLException(ex.getMessage());
+		} catch (IndexOutOfBoundsException e) {
+			throw newSQLInvalidColumnIndexException(columnIndex);
+		}
 	}
-	
+
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of
-     * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable
-     * for retrieving large LONGVARBINARY  values.
-     * <br/><br/>
+	 * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable
+	 * for retrieving large LONGVARBINARY  values.
+	 * <br/><br/>
 	 * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next
-     * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method available is
-     * called whether there is data available or not.
+	 * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method available is
+	 * called whether there is data available or not.
 	 *
-	 * @param columnName the label for the column specified with the SQL AS clause. If the SQL AS clause was not
-     * specified, then the label is the name of the column
+	 * @param columnLabel the label for the column specified with he SQL AS clause. If the SQL AS clause was not
+	 * specified, then the label is the name of the column
 	 * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the
-     * value is SQL NULL, the result is null
+	 * value is SQL NULL, the result is null
 	 * @throws SQLException if the columnLabel is not valid; if a database access error occurs or this method is called
-     * on a closed result set
+	 * on a closed result set
 	 */
 	@Override
-	public InputStream getBinaryStream(String columnName) throws SQLException {
-		return getBinaryStream(findColumn(columnName));
+	public InputStream getBinaryStream(String columnLabel) throws SQLException {
+		return getBinaryStream(findColumn(columnLabel));
 	}
 
 	/**
@@ -407,12 +403,12 @@ public class MonetResultSet extends Mone
 	public Reader getCharacterStream(int columnIndex) throws SQLException {
 		try {
 			String ss = currentBlock.getValueAsString(columnIndex - 1);
-            return (ss == null) ? null : new StringReader(ss);
+			return (ss == null) ? null : new StringReader(ss);
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -421,45 +417,45 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader
 	 * object.
 	 *
-	 * @param columnName the name of the column
+	 * @param columnLabel the name of the column
 	 * @return a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned is
-     * null in the Java programming language.
+	 * null in the Java programming language.
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Reader getCharacterStream(String columnName) throws SQLException {
-		return getCharacterStream(findColumn(columnName));
+	public Reader getCharacterStream(String columnLabel) throws SQLException {
+		return getCharacterStream(findColumn(columnLabel));
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader
-     * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns.
+	 * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns.
 	 *
 	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned is
-     * null in the Java programming language.
+	 * null in the Java programming language.
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
 	public Reader getNCharacterStream(int columnIndex) throws SQLException {
-		throw newSQLFeatureNotSupportedException("getNCharacterStream");
+		return getCharacterStream(columnIndex);
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader
-     * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns.
+	 * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns.
 	 *
-	 * @param columnName the name of the column
+	 * @param columnLabel the name of the column
 	 * @return a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned is
-     * null in the Java programming language.
+	 * null in the Java programming language.
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does
 	 *         not support this method
 	 */
 	@Override
-	public Reader getNCharacterStream(String columnName) throws SQLException {
-		throw newSQLFeatureNotSupportedException("getNCharacterStream");
+	public Reader getNCharacterStream(String columnLabel) throws SQLException {
+		return getCharacterStream(findColumn(columnLabel));
 	}
 
 	/**
@@ -477,23 +473,23 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a Blob object in the
-     * Java programming language.
+	 * Java programming language.
 	 *
-	 * @param colName the name of the column from which to retrieve the value
+	 * @param columnLabel the name of the column from which to retrieve the value
 	 * @return a Blob object representing the SQL BLOB value in the specified column
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Blob getBlob(String colName) throws SQLException {
-		return getBlob(findColumn(colName));
+	public Blob getBlob(String columnLabel) throws SQLException {
+		return getBlob(findColumn(columnLabel));
 	}
 
 	/**
@@ -511,8 +507,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -521,26 +517,26 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a Clob object in the
 	 * Java programming language.
 	 *
-	 * @param colName the name of the column from which to retrieve the value
+	 * @param columnLabel the name of the column from which to retrieve the value
 	 * @return a Clob object representing the SQL CLOB value in the specified column
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Clob getClob(String colName) throws SQLException {
-		return getClob(findColumn(colName));
+	public Clob getClob(String columnLabel) throws SQLException {
+		return getClob(findColumn(columnLabel));
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a NClob object in the
 	 * Java programming language.
 	 *
-	 * @param i the first column is 1, the second is 2, ...
+	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return a NClob object representing the SQL NCLOB value in the specified column
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public NClob getNClob(int i) throws SQLException {
+	public NClob getNClob(int columnIndex) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getNClob");
 	}
 
@@ -548,13 +544,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a NClob object in the
 	 * Java programming language.
 	 *
-	 * @param colName the name of the column from which to retrieve the value
+	 * @param columnLabel the name of the column from which to retrieve the value
 	 * @return a NClob object representing the SQL NCLOB value in the specified column
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public NClob getNClob(String colName) throws SQLException {
+	public NClob getNClob(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getNClob");
 	}
 
@@ -601,7 +597,7 @@ public class MonetResultSet extends Mone
 				case Types.CLOB:
 				case Types.BLOB:
 				case Types.LONGVARBINARY:
-				    String ss = currentBlock.getValueAsString(columnIndex - 1);
+					String ss = currentBlock.getValueAsString(columnIndex - 1);
 					return (ss == null) ? null : new BigDecimal(ss);
 				default: //OTHERS, BLOB, LONGVARBINARY, TIME...
 					throw new SQLException("Conversion from " + types[columnIndex - 1] +
@@ -610,8 +606,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -646,21 +642,21 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this
 	 * ResultSet object as a java.math.BigDecimal with full precision.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value (full precision); if the value is SQL NULL,
 	 *         the value returned is null in the Java programming language.
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public BigDecimal getBigDecimal(String columnName) throws SQLException {
-		return getBigDecimal(findColumn(columnName));
+	public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
+		return getBigDecimal(findColumn(columnLabel));
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this
 	 * ResultSet object as a java.math.BigDecimal with full precision.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @param scale the number of digits to the right of the decimal point
 	 * @return the column value (full precision); if the value is SQL NULL,
 	 *         the value returned is null in the Java programming language.
@@ -668,14 +664,14 @@ public class MonetResultSet extends Mone
 	 */
 	@Override
 	@Deprecated
-	public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
-		return getBigDecimal(findColumn(columnName), scale);
+	public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
+		return getBigDecimal(findColumn(columnLabel), scale);
 	}
 
 	// See Sun JDBC Specification 3.0 Table B-6
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a boolean in the Java
-     * programming language.
+	 * programming language.
 	 *
 	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return the column value; if the value is SQL NULL, the value returned is false
@@ -707,27 +703,27 @@ public class MonetResultSet extends Mone
 				case Types.DOUBLE:
 					double dou = currentBlock.getDoubleValue(columnIndex - 1);
 					return !currentBlock.isLastReadWasNull() && dou != 0.0d;
-                case Types.CHAR:
-                case Types.VARCHAR:
-                case Types.LONGVARCHAR:
-                case Types.CLOB:
-                case Types.BLOB:
-                case Types.LONGVARBINARY:
-                    String val = currentBlock.getValueAsString(columnIndex - 1);
-                    return val != null && !"0".equals(val) && ("1".equals(val) || Boolean.parseBoolean(val));
-                case Types.NUMERIC:
-                case Types.DECIMAL:
-                    BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
-                    return bigdec != null && bigdec.compareTo(BigDecimal.ZERO) != 0;
-                default: //OTHERS, BLOB, LONGVARBINARY, TIME...
-                    throw new SQLException("Conversion from " + types[columnIndex - 1] +
-                            " to boolean type not supported", "M1M05");
-            }
+				case Types.CHAR:
+				case Types.VARCHAR:
+				case Types.LONGVARCHAR:
+				case Types.CLOB:
+				case Types.BLOB:
+				case Types.LONGVARBINARY:
+					String val = currentBlock.getValueAsString(columnIndex - 1);
+					return val != null && !"0".equals(val) && ("1".equals(val) || Boolean.parseBoolean(val));
+				case Types.NUMERIC:
+				case Types.DECIMAL:
+					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
+					return bigdec != null && bigdec.compareTo(BigDecimal.ZERO) != 0;
+				default: //OTHERS, BLOB, LONGVARBINARY, TIME...
+					throw new SQLException("Conversion from " + types[columnIndex - 1] +
+							" to boolean type not supported", "M1M05");
+			}
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -736,13 +732,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a boolean in the Java
 	 * programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is false
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public boolean getBoolean(String columnName) throws SQLException {
-		return getBoolean(findColumn(columnName));
+	public boolean getBoolean(String columnLabel) throws SQLException {
+		return getBoolean(findColumn(columnLabel));
 	}
 
 	/**
@@ -797,8 +793,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -807,14 +803,14 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this
 	 * ResultSet object as a byte in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned
 	 *         is 0
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public byte getByte(String columnName) throws SQLException {
-		return getByte(findColumn(columnName));
+	public byte getByte(String columnLabel) throws SQLException {
+		return getByte(findColumn(columnLabel));
 	}
 
 	/**
@@ -849,8 +845,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -859,13 +855,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a byte array in the
 	 * Java programming language. The bytes represent the raw values returned by the driver.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public byte[] getBytes(String columnName) throws SQLException {
-		return getBytes(findColumn(columnName));
+	public byte[] getBytes(String columnLabel) throws SQLException {
+		return getBytes(findColumn(columnLabel));
 	}
 
 	/**
@@ -959,8 +955,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -969,13 +965,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this
 	 * ResultSet object as a double in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is 0
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public double getDouble(String columnName) throws SQLException {
-		return getDouble(findColumn(columnName));
+	public double getDouble(String columnLabel) throws SQLException {
+		return getDouble(findColumn(columnLabel));
 	}
 
 	/**
@@ -1109,8 +1105,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -1119,13 +1115,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a float in the Java
 	 * programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is 0
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public float getFloat(String columnName) throws SQLException {
-		return getFloat(findColumn(columnName));
+	public float getFloat(String columnLabel) throws SQLException {
+		return getFloat(findColumn(columnLabel));
 	}
 
 	/**
@@ -1180,8 +1176,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -1190,13 +1186,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as an int in the
 	 * Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is 0
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public int getInt(String columnName) throws SQLException {
-		return getInt(findColumn(columnName));
+	public int getInt(String columnLabel) throws SQLException {
+		return getInt(findColumn(columnLabel));
 	}
 
 	/**
@@ -1251,8 +1247,8 @@ public class MonetResultSet extends Mone
 		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        } catch (IndexOutOfBoundsException e) {
+			throw new SQLException(e);
+		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		}
 	}
@@ -1261,13 +1257,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a long in the Java
 	 * programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is 0
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public long getLong(String columnName) throws SQLException {
-		return getLong(findColumn(columnName));
+	public long getLong(String columnLabel) throws SQLException {
+		return getLong(findColumn(columnLabel));
 	}
 
 	/* helper for the anonymous class inside getMetaData */
@@ -1569,9 +1565,11 @@ public class MonetResultSet extends Mone
 								_precision[column] = 10;
 								break;
 							case Types.TIME:
+							case 2013: //Types.TIME_WITH_TIMEZONE:
 								_precision[column] = 8;
 								break;
 							case Types.TIMESTAMP:
+							case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 								_precision[column] = 19;
 								break;
 							default:
@@ -1832,8 +1830,10 @@ public class MonetResultSet extends Mone
 				case Types.DATE:
 					return getDate(columnIndex);
 				case Types.TIME:
+				case 2013: //Types.TIME_WITH_TIMEZONE:
 					return getTime(columnIndex);
 				case Types.TIMESTAMP:
+				case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 					return getTimestamp(columnIndex);
 				case Types.OTHER: {
 					// The MonetDB types: inet, json, url and uuid are all mapped to Types.OTHER in MonetDriver.typeMap
@@ -1889,8 +1889,8 @@ public class MonetResultSet extends Mone
 		} catch (IndexOutOfBoundsException e) {
 			throw newSQLInvalidColumnIndexException(columnIndex);
 		} catch (ProtocolException e) {
-            throw new SQLException(e);
-        }
+			throw new SQLException(e);
+		}
 	}
 
 	private boolean classImplementsSQLData(Class<?> cl) {
@@ -2160,6 +2160,8 @@ public class MonetResultSet extends Mone
 	@Override
 	@SuppressWarnings("unchecked")
 	public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+		if (type == null)
+			throw new SQLException("type is null", "M1M05");
 		try {
 			return (T) getObjectFromClass(columnIndex, type);
 		} catch (IndexOutOfBoundsException e) {
@@ -2223,8 +2225,10 @@ public class MonetResultSet extends Mone
 			case Types.DATE:
 				return Date.class;
 			case Types.TIME:
+			case 2013: //Types.TIME_WITH_TIMEZONE:
 				return Time.class;
 			case Types.TIMESTAMP:
+			case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 				return Timestamp.class;
 			case Types.CLOB:
 				return Clob.class;
@@ -2247,13 +2251,13 @@ public class MonetResultSet extends Mone
 	 *
 	 * This method may also be used to read database-specific abstract data types.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return a java.lang.Object holding the column value
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Object getObject(String columnName) throws SQLException {
-		return getObject(findColumn(columnName));
+	public Object getObject(String columnLabel) throws SQLException {
+		return getObject(findColumn(columnLabel));
 	}
 
 	/**
@@ -2262,24 +2266,24 @@ public class MonetResultSet extends Mone
 	 * value is an SQL NULL, the driver returns a Java null. This method uses
 	 * the specified Map object for custom mapping if appropriate.
 	 *
-	 * @param colName the name of the column from which to retrieve the value
+	 * @param columnLabel the name of the column from which to retrieve the value
 	 * @param map a java.util.Map object that contains the mapping from SQL
 	 *        type names to classes in the Java programming language
 	 * @return an Object representing the SQL value in the specified column
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Object getObject(String colName, Map<String,Class<?>> map) throws SQLException {
-		return getObject(findColumn(colName), map);
+	public Object getObject(String columnLabel, Map<String,Class<?>> map) throws SQLException {
+		return getObject(findColumn(columnLabel), map);
 	}
 
 	@Override
-	public Ref getRef(int i) throws SQLException {
+	public Ref getRef(int columnIndex) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getRef");
 	}
 
 	@Override
-	public Ref getRef(String colName) throws SQLException {
+	public Ref getRef(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getRef");
 	}
 
@@ -2312,13 +2316,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.RowId
 	 * object in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public RowId getRowId(String columnName) throws SQLException {
+	public RowId getRowId(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getRowId");
 	}
 
@@ -2384,13 +2388,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a short in the Java
 	 * programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is 0
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public short getShort(String columnName) throws SQLException {
-		return getShort(findColumn(columnName));
+	public short getShort(String columnLabel) throws SQLException {
+		return getShort(findColumn(columnLabel));
 	}
 
 	/**
@@ -2430,13 +2434,13 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this
 	 * ResultSet object as a String in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 */
 	@Override
-	public String getString(String columnName) throws SQLException {
-		return getString(findColumn(columnName));
+	public String getString(String columnLabel) throws SQLException {
+		return getString(findColumn(columnLabel));
 	}
 
 	/**
@@ -2461,27 +2465,27 @@ public class MonetResultSet extends Mone
 	 * language. It is intended for use when accessing NCHAR,NVARCHAR
 	 * and LONGNVARCHAR columns.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
-	 * @throws SQLException if the ResultSet object does not contain columnName
+	 * @throws SQLException if the ResultSet object does not contain columnLabel
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public String getNString(String columnName) throws SQLException {
-		return getNString(findColumn(columnName));
+	public String getNString(String columnLabel) throws SQLException {
+		return getString(findColumn(columnLabel));
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet as a java.sql.SQLXML object
 	 * in the Java programming language.
 	 *
-	 * @param i the first column is 1, the second is 2, ...
+	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return a SQLXML object that maps an SQL XML value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public SQLXML getSQLXML(int i) throws SQLException {
+	public SQLXML getSQLXML(int columnIndex) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getSQLXML");
 	}
 
@@ -2489,14 +2493,14 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet as a java.sql.SQLXML object
 	 * in the Java programming language.
 	 *
-	 * @param colName the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified,
-	 * then the label is the name of the column
+	 * @param columnLabel the label for the column specified with the SQL AS clause. If the SQL AS clause was not
+	 * specified, then the label is the name of the column
 	 * @return a SQLXML object that maps an SQL XML value
 	 * @throws SQLException if a database access error occurs
 	 * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method
 	 */
 	@Override
-	public SQLXML getSQLXML(String colName) throws SQLException {
+	public SQLXML getSQLXML(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("getSQLXML");
 	}
 
@@ -2531,44 +2535,44 @@ public class MonetResultSet extends Mone
 	public Date getDate(int columnIndex, Calendar cal) throws SQLException {
 		try {
 			Calendar res;
-            long millis;
-            switch (JdbcSQLTypes[columnIndex - 1]) {
-                case Types.DATE:
-                case Types.TIME:
-                case Types.TIMESTAMP:
+			long millis;
+			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.DATE:
+				case Types.TIME:
+				case Types.TIMESTAMP:
+					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
+					if(res == null) {
+						return null;
+					}
+					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					break;
+				case 2013: //Types.TIME_WITH_TIMEZONE:
+				case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					millis = res.getTimeInMillis();
 					break;
-                case 2013: //Types.TIME_WITH_TIMEZONE:
-                case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
-                    res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
+				case Types.CHAR:
+				case Types.VARCHAR:
+				case Types.LONGVARCHAR:
+				case Types.CLOB:
+				case Types.BLOB:
+				case Types.LONGVARBINARY:
+					res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.DATE);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis();
-                    break;
-                case Types.CHAR:
-                case Types.VARCHAR:
-                case Types.LONGVARCHAR:
-                case Types.CLOB:
-				case Types.BLOB:
-				case Types.LONGVARBINARY:
-                    res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.DATE);
-					if(res == null) {
-						return null;
-					}
-                    millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
-                    break;
-                default:
-                    this.addWarning("unsupported data type", "01M03");
-                    cal.clear();
-                    millis = 0;
-            }
-            return new Date(millis);
-        } catch (ClassCastException ex) {
+					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					break;
+				default:
+					this.addWarning("unsupported data type", "01M03");
+					cal.clear();
+					millis = 0;
+			}
+			return new Date(millis);
+		} catch (ClassCastException ex) {
 			throw new SQLException(ex.getMessage());
 		} catch (ProtocolException e) {
 			throw new SQLException(e);
@@ -2582,13 +2586,13 @@ public class MonetResultSet extends Mone
 	 * ResultSet object as a java.sql.Date object in the Java programming
 	 * language.
 	 *
-	 * @param columnName the SQL name of the column from which to retrieve the value
+	 * @param columnLabel the SQL name of the column from which to retrieve the value
 	 * @return the column value; if the value is SQL NULL, the value returned is null
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Date getDate(String columnName) throws SQLException {
-		return getDate(findColumn(columnName), Calendar.getInstance());
+	public Date getDate(String columnLabel) throws SQLException {
+		return getDate(findColumn(columnLabel), Calendar.getInstance());
 	}
 
 	/**
@@ -2598,14 +2602,14 @@ public class MonetResultSet extends Mone
 	 * millisecond value for the date if the underlying database does not store
 	 * timezone information.
 	 *
-	 * @param columnName the SQL name of the column from which to retrieve the value
+	 * @param columnLabel the SQL name of the column from which to retrieve the value
 	 * @param cal the java.util.Calendar object to use in constructing the date
 	 * @return the column value; if the value is SQL NULL, the value returned is null
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Date getDate(String columnName, Calendar cal) throws SQLException {
-		return getDate(findColumn(columnName), cal);
+	public Date getDate(String columnLabel, Calendar cal) throws SQLException {
+		return getDate(findColumn(columnLabel), cal);
 	}
 
 	/**
@@ -2618,7 +2622,7 @@ public class MonetResultSet extends Mone
 	 */
 	@Override
 	public Time getTime(int columnIndex) throws SQLException {
-		return getTime(columnIndex, Calendar.getInstance());
+		return getTime(columnIndex, null);
 	}
 
 	/**
@@ -2630,71 +2634,71 @@ public class MonetResultSet extends Mone
 	 *
 	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @param cal the java.util.Calendar object to use in constructing the timestamp
-	 * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null in
-	 * the Java programming language
+	 * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null in the
+	 * Java programming language
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
 	public Time getTime(int columnIndex, Calendar cal) throws SQLException {
-        try {
-            Calendar res;
-            long millis;
-            switch (JdbcSQLTypes[columnIndex - 1]) {
-                case Types.DATE:
-                case Types.TIME:
-                case Types.TIMESTAMP:
+		try {
+			Calendar res;
+			long millis;
+			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.DATE:
+				case Types.TIME:
+				case Types.TIMESTAMP:
 					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
 						return null;
 					}
 					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
 					break;
-                case 2013: //Types.TIME_WITH_TIMEZONE:
-                case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
+				case 2013: //Types.TIME_WITH_TIMEZONE:
+				case 2014: //Types.TIMESTAMP_WITH_TIMEZONE:
 					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
 						return null;
 					}
 					millis = res.getTimeInMillis();
 					break;
-                case Types.CHAR:
-                case Types.VARCHAR:
-                case Types.LONGVARCHAR:
-                case Types.CLOB:
+				case Types.CHAR:
+				case Types.VARCHAR:
+				case Types.LONGVARCHAR:
+				case Types.CLOB:
 				case Types.BLOB:
 				case Types.LONGVARBINARY:
-                    res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIME);
+					res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIME);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
-                    break;
-                default:
-                    this.addWarning("unsupported data type", "01M03");
-                    cal.clear();
-                    millis = 0;
-            }
-            return new Time(millis);
-        } catch (ClassCastException ex) {
-            throw new SQLException(ex.getMessage());
-        } catch (ProtocolException e) {
+					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					break;
+				default:
+					this.addWarning("unsupported data type", "01M03");
+					cal.clear();
+					millis = 0;
+			}
+			return new Time(millis);
+		} catch (ClassCastException ex) {
+			throw new SQLException(ex.getMessage());
+		} catch (ProtocolException e) {
 			throw new SQLException(e);
 		} catch (IndexOutOfBoundsException e) {
-            throw newSQLInvalidColumnIndexException(columnIndex);
-        }
+			throw newSQLInvalidColumnIndexException(columnIndex);
+		}
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Time
 	 * object in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Time getTime(String columnName) throws SQLException {
-		return getTime(findColumn(columnName), Calendar.getInstance());
+	public Time getTime(String columnLabel) throws SQLException {
+		return getTime(findColumn(columnLabel), null);
 	}
 
 	/**
@@ -2704,15 +2708,15 @@ public class MonetResultSet extends Mone
 	 * millisecond value for the time if the underlying database does not store
 	 * timezone information.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @param cal the java.util.Calendar object to use in constructing the timestamp
-	 * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null
-	 * in the Java programming language
+	 * @return the column value as a java.sql.Time object; if the value is SQL NULL, the value returned is null in the
+	 * Java programming language
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Time getTime(String columnName, Calendar cal) throws SQLException {
-		return getTime(findColumn(columnName), cal);
+	public Time getTime(String columnLabel, Calendar cal) throws SQLException {
+		return getTime(findColumn(columnLabel), cal);
 	}
 
 	/**
@@ -2725,7 +2729,7 @@ public class MonetResultSet extends Mone
 	 */
 	@Override
 	public Timestamp getTimestamp(int columnIndex) throws SQLException {
-		return getTimestamp(columnIndex, Calendar.getInstance());
+		return getTimestamp(columnIndex, null);
 	}
 
 	/**
@@ -2743,26 +2747,26 @@ public class MonetResultSet extends Mone
 	 */
 	@Override
 	public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
-        try {
-            Calendar res;
+		try {
+			Calendar res;
 			long millis;
 			int nanos = 0;
-            switch (JdbcSQLTypes[columnIndex - 1]) {
-                case Types.DATE:
-                case Types.TIME:
-                    res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
+			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.DATE:
+				case Types.TIME:
+					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
-                    break;
-                case 2013: //Types.TIME_WITH_TIMEZONE:
-                    res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
+					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					break;
+				case 2013: //Types.TIME_WITH_TIMEZONE:
+					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis();
-                    break;
+					millis = res.getTimeInMillis();
+					break;
 				case Types.TIMESTAMP:
 					res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1);
 					if(res == null) {
@@ -2779,46 +2783,46 @@ public class MonetResultSet extends Mone
 					nanos = currentBlock.getLastNanos();
 					millis = res.getTimeInMillis();
 					break;
-                case Types.CHAR:
-                case Types.VARCHAR:
-                case Types.LONGVARCHAR:
-                case Types.CLOB:
+				case Types.CHAR:
+				case Types.VARCHAR:
+				case Types.LONGVARCHAR:
+				case Types.CLOB:
 				case Types.BLOB:
 				case Types.LONGVARBINARY:
-                    res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIMESTAMP);
+					res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIMESTAMP);
 					if(res == null) {
 						return null;
 					}
-                    millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
-                    break;
-                default:
-                    this.addWarning("unsupported data type", "01M03");
-                    cal.clear();
-                    millis = 0;
-            }
-            Timestamp result = new Timestamp(millis);
-            result.setNanos(nanos);
-            return result;
-        } catch (ClassCastException ex) {
-            throw new SQLException(ex.getMessage());
-        } catch (ProtocolException e) {
+					millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset();
+					break;
+				default:
+					this.addWarning("unsupported data type", "01M03");
+					cal.clear();
+					millis = 0;
+			}
+			Timestamp result = new Timestamp(millis);
+			result.setNanos(nanos);
+			return result;
+		} catch (ClassCastException ex) {
+			throw new SQLException(ex.getMessage());
+		} catch (ProtocolException e) {
 			throw new SQLException(e);
 		} catch (IndexOutOfBoundsException e) {
-            throw newSQLInvalidColumnIndexException(columnIndex);
-        }
+			throw newSQLInvalidColumnIndexException(columnIndex);
+		}
 	}
 
 	/**
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp
 	 * object in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value; if the value is SQL NULL, the value returned is null
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Timestamp getTimestamp(String columnName) throws SQLException {
-		return getTimestamp(findColumn(columnName), Calendar.getInstance());
+	public Timestamp getTimestamp(String columnLabel) throws SQLException {
+		return getTimestamp(findColumn(columnLabel), null);
 	}
 
 	/**
@@ -2828,15 +2832,15 @@ public class MonetResultSet extends Mone
 	 * millisecond value for the timestamp if the underlying database does not
 	 * store timezone information.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @param cal the java.util.Calendar object to use in constructing the timestamp
 	 * @return the column value as a java.sql.Timestamp object; if the value is
 	 *         SQL NULL, the value returned is null in the Java programming language
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
-		return getTimestamp(findColumn(columnName), cal);
+	public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
+		return getTimestamp(findColumn(columnLabel), cal);
 	}
 
 	/**
@@ -2892,14 +2896,14 @@ public class MonetResultSet extends Mone
 	 * Retrieves the value of the designated column in the current row of this ResultSet object as a java.net.URL object
 	 * in the Java programming language.
 	 *
-	 * @param columnName the SQL name of the column
+	 * @param columnLabel the SQL name of the column
 	 * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null in the
 	 * Java programming language
 	 * @throws SQLException if a database access error occurs, or if a URL is malformed
 	 */
 	@Override
-	public URL getURL(String columnName) throws SQLException {
-		return getURL(findColumn(columnName));
+	public URL getURL(String columnLabel) throws SQLException {
+		return getURL(findColumn(columnLabel));
 	}
 
 	/**
@@ -3087,7 +3091,7 @@ public class MonetResultSet extends Mone
 	 *
 	 * Note: Support for the rowUpdated method is optional with a result set concurrency of CONCUR_READ_ONLY
 	 *
-	 * Returns: true if the current row is detected to have been visibly updated by the owner or another; false otherwise
+	 * Returns: true if the current row is detected to have been visibly updated by the owner or another;false otherwise
 	 *
 	 * Throws:
 	 *     SQLException - if a database access error occurs or this method is called on a closed result set
@@ -3100,21 +3104,21 @@ public class MonetResultSet extends Mone
 		return false;
 	}
 
-    /**
-     * Adds a warning to the pile of warnings this ResultSet object has. If
-     * there were no warnings (or clearWarnings was called) this warning will
-     * be the first, otherwise this warning will get appended to the current
-     * warning.
-     *
-     * @param reason the warning message
-     */
-    public void addWarning(String reason, String sqlstate) {
-        if (warnings == null) {
-            warnings = new SQLWarning(reason, sqlstate);
-        } else {
-            warnings.setNextWarning(new SQLWarning(reason, sqlstate));
-        }
-    }
+	/**
+	 * Adds a warning to the pile of warnings this ResultSet object has. If
+	 * there were no warnings (or clearWarnings was called) this warning will
+	 * be the first, otherwise this warning will get appended to the current
+	 * warning.
+	 *
+	 * @param reason the warning message
+	 */
+	public void addWarning(String reason, String sqlstate) {
+		if (warnings == null) {
+			warnings = new SQLWarning(reason, sqlstate);
+		} else {
+			warnings.setNextWarning(new SQLWarning(reason, sqlstate));
+		}
+	}
 
 	/* the next methods are all related to updateable result sets, which we currently do not support */
 	@Override
@@ -3153,7 +3157,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateArray(String columnName, Array x) throws SQLException {
+	public void updateArray(String columnLabel, Array x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateArray");
 	}
 
@@ -3173,17 +3177,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateAsciiStream(String columnName, InputStream x) throws SQLException {
+	public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateAsciiStream");
 	}
 
 	@Override
-	public void updateAsciiStream(String columnName, InputStream x, int length) throws SQLException {
+	public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateAsciiStream");
 	}
 
 	@Override
-	public void updateAsciiStream(String columnName, InputStream x, long length) throws SQLException {
+	public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateAsciiStream");
 	}
 
@@ -3193,7 +3197,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
+	public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBigDecimal");
 	}
 
@@ -3213,17 +3217,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateBinaryStream(String columnName, InputStream x) throws SQLException {
+	public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBinaryStream");
 	}
 
 	@Override
-	public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException {
+	public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBinaryStream");
 	}
 
 	@Override
-	public void updateBinaryStream(String columnName, InputStream x, long length) throws SQLException {
+	public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBinaryStream");
 	}
 
@@ -3243,17 +3247,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateBlob(String columnName, Blob x) throws SQLException {
+	public void updateBlob(String columnLabel, Blob x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBlob");
 	}
 
 	@Override
-	public void updateBlob(String columnName, InputStream s) throws SQLException {
+	public void updateBlob(String columnLabel, InputStream s) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBlob");
 	}
 
 	@Override
-	public void updateBlob(String columnName, InputStream s, long length) throws SQLException {
+	public void updateBlob(String columnLabel, InputStream s, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBlob");
 	}
 
@@ -3263,7 +3267,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateBoolean(String columnName, boolean x) throws SQLException {
+	public void updateBoolean(String columnLabel, boolean x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBoolean");
 	}
 
@@ -3273,7 +3277,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateByte(String columnName, byte x) throws SQLException {
+	public void updateByte(String columnLabel, byte x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateByte");
 	}
 
@@ -3283,7 +3287,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateBytes(String columnName, byte[] x) throws SQLException {
+	public void updateBytes(String columnLabel, byte[] x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateBytes");
 	}
 
@@ -3303,17 +3307,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateCharacterStream(String columnName, Reader reader) throws SQLException {
+	public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateCharacterStream");
 	}
 
 	@Override
-	public void updateCharacterStream(String columnName, Reader reader, int length) throws SQLException {
+	public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateCharacterStream");
 	}
 
 	@Override
-	public void updateCharacterStream(String columnName, Reader reader, long length) throws SQLException {
+	public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateCharacterStream");
 	}
 
@@ -3328,12 +3332,12 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateNCharacterStream(String columnName, Reader reader) throws SQLException {
+	public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNCharacterStream");
 	}
 
 	@Override
-	public void updateNCharacterStream(String columnName, Reader reader, long length) throws SQLException {
+	public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNCharacterStream");
 	}
 
@@ -3353,17 +3357,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateClob(String columnName, Clob x) throws SQLException {
+	public void updateClob(String columnLabel, Clob x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateClob");
 	}
 
 	@Override
-	public void updateClob(String columnName, Reader r) throws SQLException {
+	public void updateClob(String columnLabel, Reader r) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateClob");
 	}
 
 	@Override
-	public void updateClob(String columnName, Reader r, long length) throws SQLException {
+	public void updateClob(String columnLabel, Reader r, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateClob");
 	}
 
@@ -3383,17 +3387,17 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateNClob(String columnName, NClob x) throws SQLException {
+	public void updateNClob(String columnLabel, NClob x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNClob");
 	}
 
 	@Override
-	public void updateNClob(String columnName, Reader r) throws SQLException {
+	public void updateNClob(String columnLabel, Reader r) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNClob");
 	}
 
 	@Override
-	public void updateNClob(String columnName, Reader r, long length) throws SQLException {
+	public void updateNClob(String columnLabel, Reader r, long length) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNClob");
 	}
 
@@ -3403,7 +3407,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateDate(String columnName, java.sql.Date x) throws SQLException {
+	public void updateDate(String columnLabel, java.sql.Date x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateDate");
 	}
 
@@ -3413,7 +3417,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateDouble(String columnName, double x) throws SQLException {
+	public void updateDouble(String columnLabel, double x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateDouble");
 	}
 
@@ -3423,7 +3427,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateFloat(String columnName, float x) throws SQLException {
+	public void updateFloat(String columnLabel, float x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateFloat");
 	}
 
@@ -3433,7 +3437,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateInt(String columnName, int x) throws SQLException {
+	public void updateInt(String columnLabel, int x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateInt");
 	}
 
@@ -3443,7 +3447,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateLong(String columnName, long x) throws SQLException {
+	public void updateLong(String columnLabel, long x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateLong");
 	}
 
@@ -3453,7 +3457,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateNull(String columnName) throws SQLException {
+	public void updateNull(String columnLabel) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNull");
 	}
 
@@ -3468,12 +3472,12 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateObject(String columnName, Object x) throws SQLException {
+	public void updateObject(String columnLabel, Object x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateObject");
 	}
 
 	@Override
-	public void updateObject(String columnName, Object x, int scale) throws SQLException {
+	public void updateObject(String columnLabel, Object x, int scale) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateObject");
 	}
 
@@ -3483,7 +3487,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateRef(String columnName, Ref x) throws SQLException {
+	public void updateRef(String columnLabel, Ref x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateRef");
 	}
 
@@ -3508,7 +3512,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateShort(String columnName, short x) throws SQLException {
+	public void updateShort(String columnLabel, short x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateShort");
 	}
 
@@ -3518,7 +3522,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateString(String columnName, String x) throws SQLException {
+	public void updateString(String columnLabel, String x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateString");
 	}
 
@@ -3528,12 +3532,12 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateNString(String columnName, String x) throws SQLException {
+	public void updateNString(String columnLabel, String x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateNString");
 	}
 
 	@Override
-	public void updateSQLXML(String columnName, SQLXML x) throws SQLException {
+	public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateSQLXML");
 	}
 
@@ -3548,7 +3552,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateTime(String columnName, Time x) throws SQLException {
+	public void updateTime(String columnLabel, Time x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateTime");
 	}
 
@@ -3558,7 +3562,7 @@ public class MonetResultSet extends Mone
 	}
 
 	@Override
-	public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
+	public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
 		throw newSQLFeatureNotSupportedException("updateTimestamp");
 	}
 
@@ -3580,19 +3584,18 @@ public class MonetResultSet extends Mone
 
 	/**
 	 * Small helper method that formats the "Invalid Column Index number ..." message
-	 * and creates a new SQLException object whose SQLState is set to "M1M05".
+	 * and creates a new SQLDataException object whose SQLState is set to "22010": invalid indicator parameter value.
 	 *
 	 * @param colIdx the column index number
-	 * @return a new created SQLException object with SQLState M1M05
+	 * @return a new created SQLDataException object with SQLState 22010
 	 */
-	static SQLException newSQLInvalidColumnIndexException(int colIdx) {
-		return new SQLException("Invalid Column Index number: " + colIdx, "M1M05");
+	static SQLDataException newSQLInvalidColumnIndexException(int colIdx) {
+		return new SQLDataException("Invalid Column Index number: " + colIdx, "22010");
 	}
 
 	/**
 	 * Small helper method that formats the "Method ... not implemented" message
-	 * and creates a new SQLFeatureNotSupportedException object
-	 * whose SQLState is set to "0A000".
+	 * and creates a new SQLFeatureNotSupportedException object whose SQLState is set to "0A000": feature not supported.
 	 *
 	 * @param name the method name
 	 * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
@@ -11,6 +11,7 @@ package nl.cwi.monetdb.jdbc;
 import nl.cwi.monetdb.mcl.responses.*;
 import nl.cwi.monetdb.mcl.responses.ResultSetResponse;
 
+import java.io.IOException;
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.Statement;
@@ -45,7 +46,7 @@ import java.util.concurrent.locks.Reentr
  * @author Martin van Dinther
  * @version 0.7
  */
-public class MonetStatement extends MonetWrapper implements Statement {
+public class MonetStatement extends MonetWrapper implements Statement, AutoCloseable {
 	/** The parental Connection object */
 	private MonetConnection connection;
 	/** The last ResponseList object this Statement produced */
@@ -81,11 +82,10 @@ public class MonetStatement extends Mone
 	 * @param connection the connection that created this Statement
 	 * @param resultSetType type of ResultSet to produce
 	 * @param resultSetConcurrency concurrency of ResultSet to produce
-	 * @throws SQLException if an error occurs during login
 	 * @throws IllegalArgumentException is one of the arguments is null or empty
 	 */
 	MonetStatement(MonetConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
-			throws SQLException, IllegalArgumentException {
+			throws IllegalArgumentException {
 		if (connection == null) throw
 			new IllegalArgumentException("No Connection given!");
 
@@ -241,8 +241,8 @@ public class MonetStatement extends Mone
 			int count = -1;
 			if (!type) count = getUpdateCount();
 			do {
-				if (offset >= max) throw
-					new SQLException("Overflow: don't use multi statements when batching (" + max + ")", "M1M16");
+				if (offset >= max)
+					throw new SQLException("Overflow: don't use multi statements when batching (" + max + ")", "M1M16");
 				if (type) {
 					e.setNextException(new SQLException("Batch query produced a ResultSet! " +
 							"Ignoring and setting update count to value " + EXECUTE_FAILED, "M1M17"));
@@ -330,7 +330,7 @@ public class MonetStatement extends Mone
 	public boolean execute(String sql) throws SQLException {
 		return internalExecute(sql);
 	}
-	
+
 	/**
 	 * Executes the given SQL statement, which may return multiple
 	 * results, and signals the driver that any auto-generated keys
@@ -679,7 +679,7 @@ public class MonetStatement extends Mone
 
 		try {
 			return new MonetVirtualResultSet(this, columns, types, jdbcTypes, results);
-		} catch (IllegalArgumentException e) {
+		} catch (IllegalArgumentException | IOException e) {
 			throw new SQLException("Internal driver error: " + e.getMessage(), "M0M03");
 		}
 	}
@@ -1188,7 +1188,7 @@ final class MonetVirtualResultSet extend
 	private boolean closed;
 
 	MonetVirtualResultSet(Statement statement, String[] columns, String[] types, int[] jdbcTypes, Object[] results)
-			throws IllegalArgumentException {
+			throws IllegalArgumentException, IOException, SQLException {
 		super(statement, columns, types, jdbcTypes, results.length);
 		this.results = results;
 		this.closed = false;
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java
@@ -24,6 +24,7 @@ import java.net.URISyntaxException;
 import java.nio.ByteOrder;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
 import java.util.*;
 
 /**
@@ -56,7 +57,7 @@ public class MapiConnection extends Mone
 	private ByteOrder serverEndianness;
 
 	public MapiConnection(Properties props, String hash, String language, boolean blobIsBinary, boolean clobIsLongChar,
-						  String hostname, int port, String database) throws IOException {
+						  String hostname, int port, String database) {
 		super(props, hash, MapiLanguage.getLanguageFromString(language), blobIsBinary, clobIsLongChar);
 		this.hostname = hostname;
 		this.port = port;
@@ -97,16 +98,11 @@ public class MapiConnection extends Mone
 	 * @return The currently in use timeout in milliseconds
 	 */
 	@Override
-	public int getSoTimeout()  {
-		try {
-			if(protocol != null) {
-				this.soTimeout = ((OldMapiProtocol)protocol).getSocket().getSoTimeout();
-			}
-			return this.soTimeout;
-		} catch (SocketException e) {
-			this.addWarning("The socket timeout could not be get", "M1M05");
+	public int getSoTimeout() throws SocketException {
+		if(protocol != null) {
+			this.soTimeout = ((OldMapiProtocol)protocol).getSocket().getSoTimeout();
 		}
-		return -1;
+		return this.soTimeout;
 	}
 
 	/**
@@ -117,18 +113,14 @@ public class MapiConnection extends Mone
 	 * @param timeout The specified timeout, in milliseconds. A timeout of zero is interpreted as an infinite timeout
 	 */
 	@Override
-	public void setSoTimeout(int timeout)  {
+	public void setSoTimeout(int timeout) throws SocketException {
 		if (timeout < 0) {
 			throw new IllegalArgumentException("Timeout can't be negative");
 		}
-		try {
-			if(protocol != null) {
-				((OldMapiProtocol)protocol).getSocket().setSoTimeout(timeout);
-			}
-			this.soTimeout = timeout;
-		} catch (SocketException e) {
-			this.addWarning("The socket timeout could not be set", "M1M05");
+		if(protocol != null) {
+			((OldMapiProtocol)protocol).getSocket().setSoTimeout(timeout);
 		}
+		this.soTimeout = timeout;
 	}
 
 	/**
@@ -253,9 +245,9 @@ public class MapiConnection extends Mone
 			}
 		} catch (SocketTimeoutException e) {
 			close(); // JDBC 4.1 semantics, abort()
-			throw new SQLException("connection timed out", "08M33");
+			throw new SQLNonTransientConnectionException("connection timed out", "08M33");
 		} catch (IOException e) {
-			throw new SQLException(e.getMessage(), "08000");
+			throw new SQLNonTransientConnectionException(e.getMessage(), "08000");
 		}
 	}
 
--- a/tests/BugDecimalRound_Bug_3561.java
+++ b/tests/BugDecimalRound_Bug_3561.java
@@ -13,22 +13,28 @@ public class BugDecimalRound_Bug_3561 {
 	public static void main(String[] args) throws Exception {
 		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
 		Connection con = DriverManager.getConnection(args[0]);
+
 		Statement stmt1 = con.createStatement();
-		PreparedStatement st;
-		Statement stmt2;
-		ResultSet rs;
-		BigDecimal bd = new BigDecimal("112.125");
+		stmt1.executeUpdate("CREATE TABLE bug3561 (d decimal(14,4))");
 
-		stmt1.executeUpdate("CREATE TABLE bug3561 (d decimal(14,4))");
-		st = con.prepareStatement("INSERT INTO bug3561 VALUES (?)");
-		st.setBigDecimal(1, bd);
+		PreparedStatement st = con.prepareStatement("INSERT INTO bug3561 VALUES (?)");
+		st.setBigDecimal(1, new BigDecimal("112.125"));
+		st.executeUpdate();
+		st.setBigDecimal(1, new BigDecimal("212.12345"));
 		st.executeUpdate();
-		stmt2 = con.createStatement();
-		rs = stmt2.executeQuery("SELECT d FROM bug3561");
+		st.setBigDecimal(1, new BigDecimal("0.012345"));
+		st.executeUpdate();
+		st.close();
+
+		Statement stmt2 = con.createStatement();
+		ResultSet rs = stmt2.executeQuery("SELECT d FROM bug3561");
 		while (rs.next())
 			System.out.println(rs.getString(1));
 		rs.close();
+		stmt2.close();
+
 		stmt1.executeUpdate("DROP TABLE bug3561");
+		stmt1.close();
 		con.close();
 	}
 }
--- a/tests/BugExecuteUpdate_Bug_3350.java
+++ b/tests/BugExecuteUpdate_Bug_3350.java
@@ -16,15 +16,23 @@ public class BugExecuteUpdate_Bug_3350 {
 
 		final Statement stmt = con.createStatement();
 		try {
-			executeDML(stmt, "INSERT INTO sys.keywords VALUES ('Bug_3350')"); // should insert 1 row
-			executeDML(stmt, "INSERT INTO sys.keywords VALUES ('Bug_3350')"); // this will result in an SQLException due to PK uniqueness violation
+			stmt.execute("CREATE TABLE t3350 (keyword VARCHAR(30) PRIMARY KEY)");
+			con.commit();
+
+			executeDML(stmt, "INSERT INTO t3350 VALUES ('Bug_3350')"); // should insert 1 row
+			executeDML(stmt, "INSERT INTO t3350 VALUES ('Bug_3350')"); // this will result in an SQLException due to PK uniqueness violation
 			con.rollback();
 
-			executeDML(stmt, "INSERT INTO sys.keywords VALUES ('Bug_3350')"); // should insert 1 row
-			executeDML(stmt, "DELETE FROM sys.keywords WHERE \"keyword\" = 'Bug_3350'"); // should delete 1 row
-			executeDML(stmt, "DELETE FROM sys.keywords WHERE \"keyword\" = 'Bug_3350'"); // should delete 0 rows
+			executeDML(stmt, "INSERT INTO t3350 VALUES ('Bug_3350')"); // should insert 1 row
+			executeDML(stmt, "INSERT INTO t3350 VALUES ('1'), ('x'), ('3'), ('y')"); // should insert 4 rows
+			executeDML(stmt, "DELETE FROM t3350 WHERE \"keyword\" = 'Bug_3350'"); // should delete 1 row
+			executeDML(stmt, "DELETE FROM t3350 WHERE \"keyword\" = 'Bug_3350'"); // should delete 0 rows
+			executeDML(stmt, "UPDATE t3350 set \"keyword\" = keyword||'_ext'"); // should update 4 rows
+			executeDML(stmt, "DELETE FROM t3350"); // should delete 4 rows
+			con.commit();
 
-			con.rollback();
+			stmt.execute("DROP TABLE t3350");
+			con.commit();
 		} catch (SQLException se) {
 			System.out.println(se.getMessage());
 		} finally {
--- a/tests/BugResultSetMetaData_Bug_6183.java
+++ b/tests/BugResultSetMetaData_Bug_6183.java
@@ -10,7 +10,8 @@ import java.sql.*;
 
 public class BugResultSetMetaData_Bug_6183 {
 	static final String dqTblName = "\"my dq_table\"";
-	static final String[] dqColNames = {"\"my space\"", "\"my, comma_space\"", "\"my$dollar\"", "\"my#hash\"", "\"my	tab\"", "\"my	,tab_comma\"", "\"my,	comma_tab\"", "\"my\\\"backslash_doublequote\""};
+	static final String[] dqColNames = { "\"my space\"", "\"my, comma_space\"", "\"my$dollar\"", "\"my#hash\"", "\"my	tab\""
+			, "\"my	,tab_comma\"", "\"my,	comma_tab\"", "\"my\\\"backslash_doublequote\"", "\"Abc\"", "\" \"", "\"123\"" };
 
 	public static void main(String[] args) throws Exception {
 		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
new file mode 100644
--- /dev/null
+++ b/tests/Bug_Connect_as_voc_getMetaData_Failure_Bug_6388.java
@@ -0,0 +1,117 @@
+/*
+ * 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 - 2017 MonetDB B.V.
+ */
+
+import java.sql.*;
+
+public class Bug_Connect_as_voc_getMetaData_Failure_Bug_6388 {
+	public static void main(String[] args) throws SQLException
+	{
+		Connection con1 = null;
+		Statement stmt1 = null;
+
+		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
+		con1 = DriverManager.getConnection(args[0]);
+		stmt1 = con1.createStatement();
+
+		// test the creation of a table with concurrent clients
+		try {
+			System.out.println("1. CREATE USER voc");
+			stmt1.executeUpdate("CREATE USER \"voc\" WITH PASSWORD 'voc' NAME 'VOC Explorer' SCHEMA \"sys\"");
+			System.out.println("2. CREATE SCHEMA voc");
+			stmt1.executeUpdate("CREATE SCHEMA \"voc\" AUTHORIZATION \"voc\"");
+			System.out.println("3. ALTER USER voc");
+			stmt1.executeUpdate("ALTER USER \"voc\" SET SCHEMA \"voc\"");
+			System.out.println("creation succeeded :)");
+			System.out.println();
+
+			login_as_voc_and_get_MetaData(args[0].replace("=monetdb", "=voc"));
+
+			System.out.println();
+			System.out.println("Cleanup created objects");
+			System.out.println("5. ALTER USER voc");
+			stmt1.executeUpdate("ALTER USER \"voc\" SET SCHEMA \"sys\"");
+			System.out.println("6. DROP SCHEMA voc");
+			stmt1.executeUpdate("DROP SCHEMA \"voc\"");
+			System.out.println("7. DROP USER voc");
+			stmt1.executeUpdate("DROP USER \"voc\"");
+			System.out.println("cleanup succeeded :)");
+		} catch (SQLException e) {
+			System.out.println("FAILED creating user and schema voc. " + e.getMessage());
+		} finally {
+			stmt1.close();
+			con1.close();
+		}
+	}
+
+	private static void login_as_voc_and_get_MetaData(String connectString) {
+		Connection con2 = null;
+
+		try {
+			System.out.println("4.1. connect as user: voc");
+			con2 = DriverManager.getConnection(connectString);
+			System.out.println("connected :)");
+		} catch (SQLException e) {
+			System.out.println("FAILED to connect as user voc. " + e.getMessage());
+			return;
+		}
+
+		try {
+			DatabaseMetaData dbmd = con2.getMetaData();
+
+			System.out.println("4.2. getUserName()");
+			System.out.println("UserName = " + dbmd.getUserName());
+
+			System.out.println("4.3. getMaxConnections()");
+			System.out.println("MaxConnections = " + dbmd.getMaxConnections());
+
+			System.out.println("4.4. getDatabaseProductVersion()");
+			String dbmsVersion = dbmd.getDatabaseProductVersion();	// should be 11.27.1 or higher
+			boolean postJul2017 = ("11.27.1".compareTo(dbmsVersion) <= 0);
+			System.out.println("DatabaseProductVersion = " + (postJul2017 ? "11.27.+" : dbmsVersion));
+
+			System.out.println("4.5. getDatabaseMajorVersion()");
+			System.out.println("DatabaseMajorVersion = " + dbmd.getDatabaseMajorVersion());	// should be 11
+
+			System.out.println("4.6. getDatabaseMinorVersion()");
+			int dbmsMinorVersion = dbmd.getDatabaseMinorVersion();	// should be 27 or higher
+			System.out.println("DatabaseMinorVersion = " + (dbmsMinorVersion >= 27 ? "27+" : dbmsMinorVersion));
+
+			System.out.println("4.7. getTables(null, 'tmp', null, null)");
+			ResultSet rs1 = dbmd.getTables(null, "tmp", null, null);
+			if (rs1 != null) {
+				System.out.println("List Tables in schema tmp:");
+				while (rs1.next()) {
+					System.out.println(rs1.getString(3));
+				}
+				rs1.close();
+			}
+			System.out.println("completed listing Tables in schema tmp");
+
+			System.out.println("4.8. getTableTypes()");
+			rs1 = dbmd.getTableTypes();
+			if (rs1 != null) {
+				System.out.println("List TableTypes:");
+				while (rs1.next()) {
+					System.out.println(rs1.getString(1));
+				}
+				rs1.close();
+			}
+			System.out.println("completed listing TableTypes");
+
+			System.out.println("voc meta data Test completed successfully");
+		} catch (SQLException e) {
+			System.out.println("FAILED fetching MonetDatabaseMetaData. " + e.getMessage());
+		} finally {
+			try {
+				con2.close();
+			} catch (SQLException e) {
+				System.out.println("FAILED to close voc connection. " + e.getMessage());
+			}
+		}
+	}
+}
new file mode 100644
--- /dev/null
+++ b/tests/Bug_PrepStmtSetObject_CLOB_6349.java
@@ -0,0 +1,60 @@
+/*
+ * 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 - 2017 MonetDB B.V.
+ */
+
+import java.sql.*;
+
+public class Bug_PrepStmtSetObject_CLOB_6349 {
+	public static void main(String[] args) throws Exception {
+		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
+		Connection con = DriverManager.getConnection(args[0]);
+		Statement stmt = con.createStatement();
+		PreparedStatement pstmt = null;
+		ParameterMetaData pmd = null;
+		ResultSet rs = null;
+		ResultSetMetaData rsmd = null;
+
+		System.out.println("0. true\t" + con.getAutoCommit());
+
+		try {
+			stmt.executeUpdate("CREATE TABLE PrepStmtSetObject_CLOB (myint INT, myvarchar VARCHAR(15), myclob CLOB)");
+			stmt.executeUpdate("INSERT INTO PrepStmtSetObject_CLOB VALUES (123, 'A string', 'A longer string')");
+			stmt.executeUpdate("INSERT INTO PrepStmtSetObject_CLOB VALUES (NULL, NULL, NULL)");  // all NULLs
+
+			pstmt = con.prepareStatement("SELECT myclob, myvarchar, myint FROM PrepStmtSetObject_CLOB WHERE myclob = ?");
+			pmd = pstmt.getParameterMetaData();
+			System.out.println("Prepared Query has " + pmd.getParameterCount() + " parameters. Type of first is: " + pmd.getParameterTypeName(1));
+			rsmd = pstmt.getMetaData();
+			System.out.println("Prepared Query has " + rsmd.getColumnCount() + " columns. Type of first is: " + rsmd.getColumnTypeName(1));
+
+			pstmt.setObject(1, "A longer string");
+			rs = pstmt.executeQuery();
+			rsmd = rs.getMetaData();
+			System.out.println("Query ResultSet has " + rsmd.getColumnCount() + " columns. Type of first is: " + rsmd.getColumnTypeName(1));
+
+			boolean has_row = rs.next();
+			boolean has_rows = rs.next();
+			if (has_row == false || has_rows == true)
+				System.out.println("Fetching Query ResultSet failed");
+
+			stmt.executeUpdate("DROP TABLE PrepStmtSetObject_CLOB");
+
+		} catch (SQLException e) {
+			System.out.println("FAILED :( "+ e.getMessage());
+			while ((e = e.getNextException()) != null)
+				System.out.println("FAILED :( " + e.getMessage());
+			System.out.println("ABORTING TEST!!!");
+		} finally {
+			if (rs != null)    rs.close();
+			if (pstmt != null) pstmt.close();
+			stmt.close();
+		}
+
+		con.close();
+	}
+}
+
new file mode 100644
--- /dev/null
+++ b/tests/Bug_PrepStmtSetString_6382.java
@@ -0,0 +1,145 @@
+/*
+ * 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 - 2017 MonetDB B.V.
+ */
+
+import java.sql.*;
+
+import nl.cwi.monetdb.jdbc.MonetINET;
+import nl.cwi.monetdb.jdbc.MonetURL;
+
+public class Bug_PrepStmtSetString_6382 {
+	public static void main(String[] args) throws Exception {
+		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
+		Connection con = DriverManager.getConnection(args[0]);
+		System.out.println("0. true\t" + con.getAutoCommit());
+
+		Statement stmt = null;
+		PreparedStatement pstmt = null;
+		ParameterMetaData pmd = null;
+		ResultSet rs = null;
+		ResultSetMetaData rsmd = null;
+		try {
+			stmt = con.createStatement();
+			String tableName = "PrepStmtSetString_6382";
+			System.out.println("Creating table " + tableName);
+			stmt.executeUpdate("CREATE TABLE " + tableName + " (myint INT, myvarchar VARCHAR(15), myjson JSON, myuuid UUID, myurl URL, myinet INET)");
+
+			System.out.println("Inserting row 1");
+			stmt.executeUpdate("INSERT INTO " + tableName + " VALUES (1, 'row 1', '{}', uuid '34c8deb5-e608-406b-beda-6a951f73d455', 'https://www.monetdb.org/', '128.0.0.1')");
+
+			System.out.println("Inserting row 2");
+			stmt.executeUpdate("INSERT INTO " + tableName + " VALUES (2, 'row 2', '[]', NULL, NULL, NULL)");
+
+
+			System.out.println("Creating a prepared statement with 6 parameters and inserting rows using setInt(), setString(), setNull(), setNString(), setURL(), setObject().");
+			pstmt = con.prepareStatement("INSERT INTO " + tableName + " VALUES (?,?, ? ,?,? , ?)");
+			pmd = pstmt.getParameterMetaData();
+			int pcount = pmd.getParameterCount();
+			System.out.println("Prepared Statement has " + pcount + " parameters:" + (pcount != 6 ? " ERROR: Expected 6 parameters!" : ""));
+			for (int p = 1; p <= pcount; p++) {
+				System.out.println(" Parameter " + p + " type is: " + pmd.getParameterTypeName(p) + ". JDBC SQL type: " + pmd.getParameterType(p));
+			}
+
+			int row = 3;
+			pstmt.setInt(1, row);
+			pstmt.setString(2, "row " + row);
+			pstmt.setString(3, "{\"menu\": {\n  \"id\": \"file\",\n  \"value\": \"File\",\n  \"popup\": {\n    \"menuitem\": [\n      {\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},\n      {\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},\n      {\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}\n    ]\n  }\n}}");
+			pstmt.setNull(4, 0);
+			pstmt.setNull(5, 0);
+			pstmt.setNull(6, 0);
+			System.out.println("Inserting row " + row);
+			int inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+			row++;  // row 4
+			pstmt.setShort(1, (short)row);
+			pstmt.setNString(2, "row " + row);
+			pstmt.setNull(3, 0);
+			pstmt.setString(4, "4a148b7d-8d47-4e1e-a21e-09a71abf2215");
+			System.out.println("Inserting row " + row);
+			inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+			row++;  // row 5
+			pstmt.setLong(1, row);
+			pstmt.setString(2, "row " + row);
+			pstmt.setNull(4, 0);
+			pstmt.setURL(5, new java.net.URL("https://www.cwi.nl/"));
+			System.out.println("Inserting row " + row);
+			inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+			row++;  // row 6
+			pstmt.setBigDecimal(1, new java.math.BigDecimal(row));
+			pstmt.setNString(2, "row " + row);
+			pstmt.setNull(5, 0);
+			pstmt.setString(6, "127.255.255.255");
+			System.out.println("Inserting row " + row);
+			inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+			/* also test generic setObject(int, String) */
+			row++;  // row 7
+			pstmt.setObject(1, new Integer(row));
+			pstmt.setObject(2, "row " + row);
+			pstmt.setObject(3, "{\"menu\": {\n    \"header\": \"SVG Viewer\",\n    \"items\": [\n        {\"id\": \"Open\"},\n        {\"id\": \"OpenNew\", \"label\": \"Open New\"},\n        null,\n        {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},\n        {\"id\": \"ZoomOut\", \"label\": \"Zoom Out\"},\n        {\"id\": \"OriginalView\", \"label\": \"Original View\"},\n        null,\n        {\"id\": \"Quality\"},\n        {\"id\": \"Pause\"},\n        {\"id\": \"Mute\"},\n        null,\n        {\"id\": \"Help\"},\n        {\"id\": \"About\", \"label\": \"About Adobe CVG Viewer...\"}\n    ]\n}}");
+			pstmt.setObject(4, "b39dc76e-4faf-4fd9-bc1e-17df48acf764");
+			pstmt.setObject(5, "https://en.wikipedia.org/wiki/IP_address");
+			pstmt.setObject(6, "223.255.255.255");
+			System.out.println("Inserting row " + row);
+			inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+			row++;  // row 8
+			pstmt.setObject(1, new java.math.BigDecimal(row));
+			pstmt.setObject(2, "row " + row);
+			pstmt.setObject(3, null);
+			pstmt.setObject(4, java.util.UUID.fromString("ff125769-b63c-4c3c-859f-5b84a9349e24"));
+			MonetURL myURL = new MonetURL("https://en.wikipedia.org/wiki/IP_address");
+			pstmt.setObject(5, myURL);
+			MonetINET myINET = new MonetINET("223.234.245.255");
+			pstmt.setObject(6, myINET);
+			System.out.println("Inserting row " + row);
+			inserted = pstmt.executeUpdate();
+			System.out.println("Inserted " + inserted + " row");
+
+
+			System.out.println("List contents of TABLE " + tableName + " after " + row + " rows inserted");
+			rs = stmt.executeQuery("SELECT * FROM " + tableName + " ORDER BY 1");
+			rsmd = rs.getMetaData();
+			int colcount = rsmd.getColumnCount();
+			System.out.println("Query has " + colcount + " output columns." + (colcount != 6 ? " ERROR: Expected 6 columns!" : ""));
+			row = 0;
+			while (rs.next()) {
+				System.out.print("row " + ++row);
+				for (int c = 1; c <= colcount; c++) {
+					System.out.print("\t" + rs.getString(c));
+				}
+				System.out.println();
+			}
+
+			System.out.println();
+			System.out.println("Cleanup TABLE " + tableName);
+			stmt.executeUpdate("DROP TABLE " + tableName);
+			System.out.println("Test completed successfully");
+		} catch (SQLException e) {
+			System.err.println("FAILED :( "+ e.getMessage());
+			while ((e = e.getNextException()) != null)
+				System.err.println("FAILED :( " + e.getMessage());
+			System.err.println("ABORTING TEST!!!");
+		} finally {
+			if (rs != null)
+				rs.close();
+			if (pstmt != null)
+				pstmt.close();
+			if (stmt != null)
+				stmt.close();
+			con.close();
+		}
+	}
+}
+
--- a/tests/Test_Dobjects.java
+++ b/tests/Test_Dobjects.java
@@ -7,37 +7,36 @@
  */
 
 import java.sql.*;
-import java.util.*;
 
 public class Test_Dobjects {
 	private static void dumpResultSet(ResultSet rs) throws SQLException {
 		ResultSetMetaData rsmd = rs.getMetaData();
-		System.out.println("Resultset with " + rsmd.getColumnCount() + " columns");
-		for (int col = 1; col <= rsmd.getColumnCount(); col++) {
+		int columnCount = rsmd.getColumnCount();
+		System.out.println("Resultset with " + columnCount + " columns");
+		for (int col = 1; col <= columnCount; col++) {
 			System.out.print(rsmd.getColumnName(col) + "\t");
 		}
 		System.out.println();
 		while (rs.next()) {
-			for (int col = 1; col <= rsmd.getColumnCount(); col++) {
+			for (int col = 1; col <= columnCount; col++) {
 				System.out.print(rs.getString(col) + "\t");
 			}
 			System.out.println();
 		}
+		rs.close();
 	}
 
 	public static void main(String[] args) throws Exception {
 		// Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");	// not needed anymore for self registering JDBC drivers
 		Connection con = DriverManager.getConnection(args[0]);
-		Statement stmt = con.createStatement();
-		PreparedStatement pstmt;
 		DatabaseMetaData dbmd = con.getMetaData();
-
 		try {
 			// inspect the catalog by use of dbmd functions
 			dumpResultSet(dbmd.getCatalogs());
 //			dumpResultSet(dbmd.getSchemas());	// this produces different outputs on different platforms due to dependency on SAMTOOLS and NETCDF. so exclude it
 			dumpResultSet(dbmd.getSchemas(null, "sys"));
-			dumpResultSet(dbmd.getTables(null, "sys", null, null));
+//			dumpResultSet(dbmd.getTables(null, "sys", null, null));	// this produces different outputs on different platforms due to dependency on Geom and NETCDF.
+			dumpResultSet(dbmd.getTables(null, "tmp", null, null));	// schema tmp has 6 tables
 			dumpResultSet(dbmd.getUDTs(null, "sys", null, null));
 			int[] UDTtypes = { Types.STRUCT, Types.DISTINCT };
 			dumpResultSet(dbmd.getUDTs(null, "sys", null, UDTtypes));
@@ -45,7 +44,6 @@ public class Test_Dobjects {
 			System.out.println("FAILED :( "+ e.getMessage());
 			System.out.println("ABORTING TEST!!!");
 		}
-
 		con.close();
 	}
 }
--- a/tests/Test_PSmetadata.java
+++ b/tests/Test_PSmetadata.java
@@ -77,19 +77,4 @@ public class Test_PSmetadata {
 		con.rollback();
 		con.close();
 	}
-
-	private static String isInstance(Object obj, String type) {
-		if (obj == null)
-			return("(null)");
-		try {
-			Class c = Class.forName(type);
-			if (c.isInstance(obj)) {
-				return(obj.getClass().getName() + " is an instance of " + type);
-			} else {
-				return(obj.getClass().getName() + " is NOT an instance of " + type);
-			}
-		} catch (ClassNotFoundException e) {
-			return("No such class: " + type);
-		}
-	}
 }
--- a/tests/build.xml
+++ b/tests/build.xml
@@ -18,7 +18,7 @@ Copyright 1997 - July 2008 CWI, August 2
 <project name="JDBCTests" default="compile" basedir=".">
 
   <property file="build.properties" />
-  <property file="../build.properties"/> <!-- included for version -->
+  <property file="../build.properties" /> <!-- included for version -->
 
   <!-- set global properties for this build -->
   <property name="srcdir"    value="." />
@@ -30,7 +30,8 @@ Copyright 1997 - July 2008 CWI, August 2
     value="jdbc:monetdb://localhost/?user=monetdb&amp;password=monetdb${debug}" />
   <property name="jdbctests-jar"
     value="${jardir}/jdbctests.jar" />
-  <property name="jvm.version" value="1.7"/>
+  <property name="jvm.version" value="1.7" />
+  <property name="javac.flags" value="-Xlint:-options" />
 
   <!-- Prepares the build directory -->
   <target name="prepare">
@@ -94,13 +95,13 @@ Copyright 1997 - July 2008 CWI, August 2
   <!-- Run tests -->
   <target name="test">
     <antcall target="Test_Cautocommit" />
-    <antcall target="Test_Cforkbomb" />
+    <!-- <antcall target="Test_Cforkbomb" /> -->
     <antcall target="Test_CisValid" />
     <antcall target="Test_Clargequery" />
     <antcall target="Test_Cmanycon" />
     <antcall target="Test_Creplysize" />
     <antcall target="Test_Csavepoints" />
-    <antcall target="Test_Csendthread" />
+    <!-- <antcall target="Test_Csendthread" /> -->
     <antcall target="Test_Ctransaction" />
     <antcall target="Test_Dobjects" />
     <antcall target="Test_FetchSize" />
@@ -132,6 +133,9 @@ Copyright 1997 - July 2008 CWI, August 2
     <antcall target="BugExecuteUpdate_Bug_3350" />
     <antcall target="BugSetQueryTimeout_Bug_3357" />
     <antcall target="BugResultSetMetaData_Bug_6183" />
+    <antcall target="Bug_PrepStmtSetObject_CLOB_6349" />
+    <antcall target="Bug_Connect_as_voc_getMetaData_Failure_Bug_6388" />
+    <antcall target="Bug_PrepStmtSetString_6382" />
   </target>
 
   <target name="test_class" depends="compile,jdbc">
@@ -381,4 +385,22 @@ Copyright 1997 - July 2008 CWI, August 2
     </antcall>
   </target>
 
+  <target name="Bug_PrepStmtSetObject_CLOB_6349">
+    <antcall target="test_class">
+      <param name="test.class" value="Bug_PrepStmtSetObject_CLOB_6349" />
+    </antcall>
+  </target>
+
+  <target name="Bug_Connect_as_voc_getMetaData_Failure_Bug_6388">
+    <antcall target="test_class">
+      <param name="test.class" value="Bug_Connect_as_voc_getMetaData_Failure_Bug_6388" />
+    </antcall>
+  </target>
+
+  <target name="Bug_PrepStmtSetString_6382">
+    <antcall target="test_class">
+      <param name="test.class" value="Bug_PrepStmtSetString_6382" />
+    </antcall>
+  </target>
+
 </project>