changeset 65:e605cdd6373f embedded

More cleaning. Created the responses layer. The JDBC embedded connection will be compatible with the standard embedded API.
author Pedro Ferreira <pedro.ferreira@monetdbsolutions.com>
date Thu, 01 Dec 2016 20:45:02 +0100 (2016-12-01)
parents bb0d66ad7dc6 (current diff) 6cc63d6cb224 (diff)
children 7307caacc2d5
files src/main/java/nl/cwi/monetdb/embedded/env/IEmbeddedConnection.java src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java 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/EmbeddedConnection.java src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedMonetDB.java src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java src/main/java/nl/cwi/monetdb/mcl/io/InternalConnection.java src/main/java/nl/cwi/monetdb/mcl/io/JDBCEmbeddedConnection.java src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedHeaderLineParser.java src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedStartOfHeaderParser.java src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedTupleLineParser.java src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java src/main/java/nl/cwi/monetdb/responses/AutoCommitResponse.java src/main/java/nl/cwi/monetdb/responses/ResponseList.java src/main/java/nl/cwi/monetdb/responses/ResultSetResponse.java src/main/java/nl/cwi/monetdb/responses/SendThread.java
diffstat 29 files changed, 853 insertions(+), 957 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,23 @@
 # ChangeLog file for java
 # This file is updated with Maddlog
 
+* Thu Nov 17 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- The MapiSocket object now supports getting and setting the
+  socket timeout, even before the TCP socket is created.  To set
+  the socket timeout specify it in the JDBC URL, for example:
+    jdbc:monetdb://localhost:50000/demo?so_timeout=8000
+  This enables the timeout and sets it to 8000 milliseconds (= 8 seconds).
+  By default the timeout is not set, so wait infinitely.
+
+* Thu Nov 10 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
+- Implemented Connection methods: getClientInfo(name) and getClientInfo().
+  They used to return null and empty Properties object.
+  Corrected implementation of Connection methods: setClientInfo(name, value)
+  and setClientInfo(properties). They are now processed as expected.
+  Corrected implementation of Connection.setHoldability(holdability). It now
+  throws an SQLFeatureNotSupportedException when holdability is not
+  ResultSet.HOLD_CURSORS_OVER_COMMIT (which is the only supported holdability).
+
 * Thu Oct 13 2016 Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
 - Corrected implementation of java.sql.Wrapper methods isWrapperFor()
   and unwrap().  They now properly return expected results instead of
--- a/release.txt
+++ b/release.txt
@@ -5,41 +5,39 @@ Release date: 2016-07-13
 This JDBC driver is designed for use with MonetDB, a main-memory
 database.  For more information see https://www.monetdb.org/.
 
+The JDBC driver complies to JDBC 4.1 definition, see
+ http://docs.oracle.com/javase/7/docs/technotes/guides/jdbc/index.html
+
+Note: as of Jul2015 release we compile all the java sources to target: Java 1.7
+so you need a JRE/JDK of version 1.7 or higher to use it.
+
 Within the current implementation not all functionalities of the JDBC
 interface are available.  It is believed, however, that this
 implementation is rich enough to be suitable for a majority of
 application settings.
-Note that this driver is JDBC4 compatible, and hence cannot be compiled
-with Java 1.5 and earlier.
-As of Jul2015 release we compile the java sources to target: Java 1.7.
 
-Below a list of supported features can be found.  Please read this list
-if you intend to use this driver.
+Below a list of (un)supported features can be found.
+Please read this list if you intend to use this driver.
 
 If you feel some features are missing or have encountered an issue/bug,
 please let us know at our bugtracker:
-  https://bugs.monetdb.org/Developers/ReportingABug
+  https://www.monetdb.org/bugzilla/
+
 
-Currently implemented JDBC interfaces:
+Currently implemented JDBC 4.1 interfaces include:
   * java.sql.Driver
 
-  * javax.sql.DataSource (not tested)
-
   * java.sql.Connection
     The next features/methods are NOT implemented:
-    - createStatement with result set holdability
-    - nativeSQL (there is no query parsing for JDBC escapes yet)
-    - prepareCall (CallableStatement not supported)
-    - prepareStatement with column indices or names
-    - setCatalog (there is no catalog)
-    - setHoldability (close/hold cursors over commit is not
-      configurable)
-    - isReadOnly/setReadOnly (updateable result sets are not supported at
-      all)
     - createArrayOf
     - createBlob, createClob, createNClob
     - createStruct
     - createSQLXML
+    - createStatement with result set holdability
+    - prepareCall (CallableStatement is not supported)
+    - prepareStatement with column indices or names
+    - setHoldability (close/hold cursors over commit is not
+      configurable)
   NOTE: be sure to check for warnings after setting concurrencies or
         isolation levels; MonetDB currently does not support anything
         else but "fully serializable" transactions.
@@ -48,19 +46,19 @@ Currently implemented JDBC interfaces:
 
   * java.sql.Statement
     The next features/methods are NOT implemented:
-    - cancel/getQueryTimeout/setQueryTimeout (query execution cannot be
-      terminated, once started)
+    - cancel (query execution cannot be terminated, once started)
     - execute with column indices or names
     - executeUpdate with column indices or names
-    - getMaxFieldSize/setMaxFieldSize
+    - setMaxFieldSize
     - setCursorName
-    - setEscapeProcessing
+    - setEscapeProcessing on
 
   * java.sql.PreparedStatement
     The next features/methods are NOT implemented:
     - setArray
     - setAsciiStream, setBinaryStream, setUnicodeStream
-    - setBlob, setNClob, setNString
+    - setBlob
+    - setNCharacterStream, setNClob, setNString
     - setRef, setRowId, setSQLXML, setURL
 
   * java.sql.ParameterMetaData
@@ -68,14 +66,17 @@ Currently implemented JDBC interfaces:
   * java.sql.ResultSet
     The next features/methods are NOT implemented:
     - getArray
-    - getAsciiStream, getBinaryStream, getUnicodeStream
-    - getRef, getURL
+    - getAsciiStream, getUnicodeStream
+    - getNCharacterStream, getNClob, getNString
+    - getRef, getRowId, getSQLXML
     - all methods related to updateable result sets
 
   * java.sql.ResultSetMetaData
 
   * java.sql.SavePoint
 
+  * java.sql.Wrapper
+
   * java.sql.Blob
     A simple implementation using a byte[] to store the whole BLOB
     The next features/methods are NOT implemented:
@@ -89,7 +90,18 @@ Currently implemented JDBC interfaces:
     - setAsciiStream
     - setCharacterStream
 
+  * javax.sql.DataSource (not tested)
 
-- Auto-commit behaviour is defined by the server which handles the
-  auto-commit.  This is in general in line with the JDBC standard.
 
+The next java.sql.* interfaces are NOT implemented:
+  * java.sql.Array
+  * java.sql.CallableStatement  (use Statement or PreparedStatement instead)
+  * java.sql.NClob
+  * java.sql.Ref
+  * java.sql.Rowid
+  * java.sql.SQLData
+  * java.sql.SQLInput
+  * java.sql.SQLOutput
+  * java.sql.SQLXML
+  * java.sql.Struct
+
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/embedded/env/IEmbeddedConnection.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package nl.cwi.monetdb.embedded.env;
-
-/**
- * Created by ferreira on 11/24/16.
- */
-public interface IEmbeddedConnection {
-
-    long getConnectionPointer();
-
-    void closeConnectionImplementation();
-}
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java
+++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java
@@ -22,9 +22,9 @@ import java.util.concurrent.ConcurrentHa
  *
  * @author <a href="mailto:pedro.ferreira@monetdbsolutions.com">Pedro Ferreira</a>
  */
-public final class MonetDBEmbeddedConnection implements IEmbeddedConnection {
+public class MonetDBEmbeddedConnection {
 
-	private final long connectionPointer;
+	protected final long connectionPointer;
 
     private final ConcurrentHashMap<Long, AbstractConnectionResult> results = new ConcurrentHashMap<>();
 
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java
+++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java
@@ -8,8 +8,7 @@
 
 package nl.cwi.monetdb.embedded.env;
 
-import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB;
-import nl.cwi.monetdb.mcl.io.InternalConnection;
+import nl.cwi.monetdb.mcl.io.JDBCEmbeddedConnection;
 
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -115,7 +114,7 @@ public final class MonetDBEmbeddedDataba
         if(MonetDBEmbeddedDatabase == null) {
             throw new MonetDBEmbeddedException("The database is not running!");
         } else {
-            for(IEmbeddedConnection mdbec : MonetDBEmbeddedDatabase.connections.values()) {
+            for(MonetDBEmbeddedConnection mdbec : MonetDBEmbeddedDatabase.connections.values()) {
                 mdbec.closeConnectionImplementation();
             }
             MonetDBEmbeddedDatabase.connections.clear();
@@ -139,7 +138,7 @@ public final class MonetDBEmbeddedDataba
 
     private final boolean sequentialFlag;
 
-    private final ConcurrentHashMap<Long, IEmbeddedConnection> connections = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<Long, MonetDBEmbeddedConnection> connections = new ConcurrentHashMap<>();
 
     private MonetDBEmbeddedDatabase(String dbDirectory, boolean silentFlag, boolean sequentialFlag) {
         this.databaseDirectory = dbDirectory;
@@ -163,23 +162,13 @@ public final class MonetDBEmbeddedDataba
         }
     }
 
-    /*
-     * Creates a connection on the database, set on the default schema asynchronously.
-     *
-     * @return A MonetDBEmbeddedConnection instance
-     * @throws MonetDBEmbeddedException If the database is not running or an error in the database occurred
-     */
-    /*public CompletableFuture<MonetDBEmbeddedConnection> createConnectionAsync() throws MonetDBEmbeddedException {
-        return CompletableFuture.supplyAsync(() -> this.createConnectionInternal());
-    }*/
-
-    public static InternalConnection AddJDBCEmbeddedConnection() throws MonetDBEmbeddedException {
+    public static JDBCEmbeddedConnection CreateJDBCEmbeddedConnection() throws MonetDBEmbeddedException {
         if(MonetDBEmbeddedDatabase == null) {
             throw new MonetDBEmbeddedException("The database is not running!");
         } else {
-            InternalConnection res = MonetDBEmbeddedDatabase.createJDBCConnectionInternal();
-            MonetDBEmbeddedDatabase.connections.put(res.getConnectionPointer(), res);
-            return res;
+            JDBCEmbeddedConnection con = MonetDBEmbeddedDatabase.createJDBCEmbeddedConnectionInternal();
+            MonetDBEmbeddedDatabase.connections.put(con.getConnectionPointer(), con);
+            return con;
         }
     }
 
@@ -210,5 +199,5 @@ public final class MonetDBEmbeddedDataba
     /**
      * Internal implementation to create a JDBC embeddded connection on this database.
      */
-    private native InternalConnection createJDBCConnectionInternal() throws MonetDBEmbeddedException;
+    private native JDBCEmbeddedConnection createJDBCEmbeddedConnectionInternal() throws MonetDBEmbeddedException;
 }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -7,10 +7,9 @@ import nl.cwi.monetdb.mcl.connection.Deb
 import nl.cwi.monetdb.mcl.connection.MonetDBLanguage;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 import nl.cwi.monetdb.responses.ResponseList;
-import nl.cwi.monetdb.responses.SendThread;
+import nl.cwi.monetdb.mcl.connection.SendThread;
 
 import java.io.*;
-import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.sql.*;
 import java.util.*;
@@ -38,16 +37,15 @@ import java.util.concurrent.Executor;
  * The current state of this connection is that it nearly implements the
  * whole Connection interface.
  *
- * @author Fabian Groffen
- * @version 1.2
+ * @author Martin van Dinther
+ * @version 1.3
  */
 public abstract class MonetConnection extends MonetWrapper implements Connection {
 
     /** the successful processed input properties */
-    private final Properties conn_props;
-
+    protected final Properties conn_props;
     /** The language to connect with */
-    protected MonetDBLanguage currentMonetDBLanguage = MonetDBLanguage.LANG_SQL;
+    protected MonetDBLanguage language;
     /** The database to connect to */
     protected String database;
     /** Authentication hash method */
@@ -96,17 +94,17 @@ public abstract class MonetConnection ex
         this.conn_props = props;
         this.database = database;
         this.hash = hash;
-        this.currentMonetDBLanguage = MonetDBLanguage.GetLanguageFromString(language);
+        this.language = MonetDBLanguage.GetLanguageFromString(language);
         this.blobIsBinary = blobIsBinary;
         this.isDebugging = isDebugging;
     }
 
-    public MonetDBLanguage getCurrentMonetDBLanguage() {
-        return currentMonetDBLanguage;
+    public MonetDBLanguage getLanguage() {
+        return language;
     }
 
-    public void setCurrentMonetDBLanguage(MonetDBLanguage currentMonetDBLanguage) {
-        this.currentMonetDBLanguage = currentMonetDBLanguage;
+    public void setLanguage(MonetDBLanguage language) {
+        this.language = language;
     }
 
     public void setDebugging(String filename) throws IOException {
@@ -129,9 +127,9 @@ public abstract class MonetConnection ex
 
     public abstract int getBlockSize();
 
-    public abstract int getSoTimeout() throws SocketException;
+    public abstract int getSoTimeout();
 
-    public abstract void setSoTimeout(int s) throws SocketException;
+    public abstract void setSoTimeout(int s);
 
     public abstract void closeUnderlyingConnection() throws IOException;
 
@@ -227,44 +225,6 @@ public abstract class MonetConnection ex
     }
 
     /**
-     * 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 Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        throw new SQLFeatureNotSupportedException("createArrayOf(String, Object[]) not supported", "0A000");
-    }
-
-    /**
      * 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
@@ -341,88 +301,6 @@ public abstract class MonetConnection ex
     }
 
     /**
-     * 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 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
-     */
-    @Override
-    public Blob createBlob() throws SQLException {
-        throw new SQLFeatureNotSupportedException("createBlob() 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 MonetClob objects that can be filled in
-     */
-    @Override
-    public 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
-     */
-    @Override
-    public 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
-     */
-    @Override
-    public SQLXML createSQLXML() throws SQLException {
-        throw new SQLFeatureNotSupportedException("createSQLXML() not supported", "0A000");
-    }
-
-    /**
      * Retrieves the current auto-commit mode for this Connection
      * object.
      *
@@ -449,31 +327,6 @@ public abstract class MonetConnection ex
     }
 
     /**
-     * Not implemented by MonetDB's JDBC driver.
-     *
-     * @param name The name of the client info property to retrieve
-     * @return The value of the client info property specified
-     */
-    @Override
-    public String getClientInfo(String name) {
-        // This method will also return null if the specified client
-        // info property name is not supported by the driver.
-        return null;
-    }
-
-    /**
-     * Not implemented by MonetDB's JDBC driver.
-     *
-     * @return A Properties object that contains the name and current
-     *         value of each of the client info properties supported by
-     *         the driver.
-     */
-    @Override
-    public Properties getClientInfo() {
-        return new Properties();
-    }
-
-    /**
      * Retrieves the current holdability of ResultSet objects created
      * using this Connection object.
      *
@@ -500,7 +353,7 @@ public abstract class MonetConnection ex
      */
     @Override
     public DatabaseMetaData getMetaData() throws SQLException {
-        if (this.currentMonetDBLanguage != MonetDBLanguage.LANG_SQL) {
+        if (this.language != MonetDBLanguage.LANG_SQL) {
             throw new SQLException("This method is only supported in SQL mode", "M0M04");
         }
         return new MonetDatabaseMetaData(this);
@@ -590,49 +443,6 @@ public abstract class MonetConnection ex
         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
-     */
-    @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 select 1;
-        Statement stmt = null;
-        try {
-            stmt = createStatement();
-            // the timeout parameter is ignored here, since
-            // MonetStatement.setQueryTimeout(timeout) is not supported.
-            stmt.executeQuery("SELECT 1");
-            stmt.close();
-            return true;
-        } catch (Exception e) {
-            if (stmt != null) {
-                try {
-                    stmt.close();
-                } catch (Exception e2) {}
-            }
-        }
-        return false;
-    }
-
     @Override
     public String nativeSQL(String sql) {return sql;}
 
@@ -916,31 +726,6 @@ public abstract class MonetConnection ex
     }
 
     /**
-     * Not implemented by MonetDB's JDBC driver.
-     *
-     * @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.
-     */
-    @Override
-    public void setClientInfo(String name, String value) {
-        addWarning("clientInfo: " + name + "is not a recognised property", "01M07");
-    }
-
-    /**
-     * Not implemented by MonetDB's JDBC driver.
-     *
-     * @param props The list of client info properties to set
-     */
-    @Override
-    public void setClientInfo(Properties props) {
-        for (Map.Entry<Object, Object> entry : props.entrySet()) {
-            setClientInfo(entry.getKey().toString(), entry.getValue().toString());
-        }
-    }
-
-    /**
      * 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().
@@ -1046,7 +831,8 @@ public abstract class MonetConnection ex
     @Override
     public void setTransactionIsolation(int level) {
         if (level != TRANSACTION_SERIALIZABLE) {
-            addWarning("MonetDB only supports fully serializable " + "transactions, continuing with transaction level " +
+            addWarning("MonetDB only supports fully serializable " +
+                    "transactions, continuing with transaction level " +
                     "raised to TRANSACTION_SERIALIZABLE", "01M09");
         }
     }
@@ -1065,8 +851,7 @@ public abstract class MonetConnection ex
     }
 
     /**
-     * Returns a string identifying this Connection to the MonetDB
-     * server.
+     * Returns a string identifying this Connection to the MonetDB server.
      *
      * @return a String representing this Object
      */
@@ -1075,7 +860,325 @@ public abstract class MonetConnection ex
         return "MonetDB Connection (" + this.getJDBCURL() + ") " + (closed ? "connected" : "disconnected");
     }
 
-    //== 1.7 methods (JDBC 4.1)
+    //== Java 1.6 methods (JDBC 4.0)
+
+    /**
+     * 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");
+    }
+
+    /**
+     * 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 {
+        byte[] buf = new byte[1];
+        return new MonetBlob(buf);
+    }
+
+    /**
+     * 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");
+    }
+
+    /**
+     * 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;
+
+        // 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 e2) {}
+            }
+            if (stmt != null) {
+                try {
+                    stmt.close();
+                } catch (Exception e2) {}
+            }
+        }
+        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);
+    }
+
+    /**
+     * 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("debug") ||
+                name.equals("hash") ||
+                name.equals("treat_blob_as_binary")) {
+            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());
+            }
+        }
+    }
+
+    //== Java 1.7 methods (JDBC 4.1)
 
     /**
      * Sets the given schema name to access.
@@ -1083,14 +1186,20 @@ public abstract class MonetConnection ex
      * @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) {
+        if (closed)
             throw new SQLException("Cannot call on closed Connection", "M1M20");
-        }
-        if (schema != null) {
-            createStatement().execute("SET SCHEMA \"" + schema + "\"");
+        if (schema == null)
+            throw new SQLException("Missing schema name", "M1M05");
+
+        Statement st = createStatement();
+        try {
+            st.execute("SET SCHEMA \"" + schema + "\"");
+        } finally {
+            st.close();
         }
     }
 
@@ -1178,11 +1287,7 @@ public abstract class MonetConnection ex
             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 SQLException(e.getMessage(), "08000");
-        }
+        this.setSoTimeout(millis);
     }
 
     /**
@@ -1200,11 +1305,7 @@ public abstract class MonetConnection ex
         if (closed) {
             throw new SQLException("Cannot call on closed Connection", "M1M20");
         }
-        try {
-            return this.getSoTimeout();
-        } catch (SocketException e) {
-            throw new SQLException(e.getMessage(), "08000");
-        }
+        return this.getSoTimeout();
     }
 
     //== end methods of interface Connection
@@ -1228,11 +1329,10 @@ public abstract class MonetConnection ex
     public void sendIndependentCommand(String command) throws SQLException {
         synchronized (this) {
             try {
-                out.writeLine(server.getQueryTemplateHeader(0) + command + server.getQueryTemplateHeader(1));
+                out.writeLine(language.getQueryTemplateIndex(0) + command + language.getQueryTemplateIndex(1));
                 String error = in.waitForPrompt();
                 if (error != null)
-                    throw new SQLException(error.substring(6),
-                            error.substring(0, 5));
+                    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");
@@ -1255,11 +1355,10 @@ public abstract class MonetConnection ex
         // send X command
         synchronized (this) {
             try {
-                out.writeLine(server.getCommandTemplateHeader(0) + command + server.getCommandTemplateHeader(1));
+                out.writeLine(language.getCommandTemplateIndex(0) + command + language.getCommandTemplateIndex(1));
                 String error = in.waitForPrompt();
                 if (error != null)
-                    throw new SQLException(error.substring(6),
-                            error.substring(0, 5));
+                    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");
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDatabaseMetaData.java
@@ -3800,10 +3800,11 @@ public class MonetDatabaseMetaData exten
 		"SELECT 'user', 1024, '', 'user name to login to MonetDB server' UNION ALL " +
 		"SELECT 'password', 128, '', 'password for user name to login to MonetDB server' UNION ALL " +
 		"SELECT 'language', 16, 'sql', 'language (sql or mal) used to parse commands in MonetDB server' UNION ALL " +
+		"SELECT 'database', 1024, 'demo', 'name of database. It matches the dbfarm subdirectory name' UNION ALL " +
 		"SELECT 'debug', 5, 'false', 'boolean flag true or false' UNION ALL " +
 		"SELECT 'hash', 128, '', 'hash string' UNION ALL " +
 		"SELECT 'treat_blob_as_binary', 5, 'false', 'boolean flag true or false' UNION ALL " +
-		"SELECT 'so_timeout', 10, '0', 'timeout of communication socket. 0 means no timeout is set' " +
+		"SELECT 'so_timeout', 10, '0', 'timeout (in milliseconds) of communication socket. 0 means no timeout is set' " +
 		"ORDER BY \"NAME\"";
 
 		return executeMetaDataQuery(query);
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
@@ -280,7 +280,7 @@ public class MonetPreparedStatement
 	 *                      statement does not return a ResultSet object
 	 */
 	@Override
-	public ResultSet executeQuery() throws SQLException{
+	public ResultSet executeQuery() throws SQLException {
 		if (!execute())
 			throw new SQLException("Query did not produce a result set", "M1M19");
 
@@ -949,7 +949,7 @@ public class MonetPreparedStatement
 	 */
 	@Override
 	public void setArray(int i, Array x) throws SQLException {
-		throw new SQLException("Operation setArray(int i, Array x) currently not supported!", "0A000");
+		throw newSQLFeatureNotSupportedException("setArray");
 	}
 
 	/**
@@ -1035,31 +1035,29 @@ public class MonetPreparedStatement
 	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public void setBigDecimal(int idx, BigDecimal x)
-	    throws SQLException
-	{
-	  // get array position
-	  int i = getParamIdx(idx);
+	public void setBigDecimal(int idx, BigDecimal x) throws SQLException {
+		// get array position
+		int i = getParamIdx(idx);
 
-	  // round to the scale of the DB:
-	  x = x.setScale(scale[i], RoundingMode.HALF_UP);
+		// round to the scale of the DB:
+		x = x.setScale(scale[i], RoundingMode.HALF_UP);
+
+		// if precision is now greater than that of the db, throw an error:
+		if (x.precision() > digits[i]) {
+			throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003");
+		}
 
-	  // if precision is now greater than that of the db, throw an error:
-	  if (x.precision() > digits[i]) {
-	    throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003");
-	  }
-
-	  // MonetDB doesn't like leading 0's, since it counts them as part of
-	  // the precision, so let's strip them off. (But be careful not to do
-	  // this to the exact number "0".)  Also strip off trailing
-	  // numbers that are inherent to the double representation.
-	  String xStr = x.toPlainString();
-	  int dot = xStr.indexOf('.');
-	  if (dot >= 0)
-	    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);
+		// MonetDB doesn't like leading 0's, since it counts them as part of
+		// the precision, so let's strip them off. (But be careful not to do
+		// this to the exact number "0".)  Also strip off trailing
+		// numbers that are inherent to the double representation.
+		String xStr = x.toPlainString();
+		int dot = xStr.indexOf('.');
+		if (dot >= 0)
+			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);
 	}
 
 	/**
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
@@ -10,6 +10,7 @@ package nl.cwi.monetdb.jdbc;
 
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 import nl.cwi.monetdb.mcl.parser.TupleLineParser;
+import nl.cwi.monetdb.responses.ResultSetResponse;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -76,7 +77,7 @@ public class MonetResultSet extends Mone
 
 	// a blank final is immutable once assigned in the constructor
 	/** A Header to retrieve lines from */
-	private final MonetConnection.ResultSetResponse header;
+	private final ResultSetResponse header;
 	/** The names of the columns in this ResultSet */
 	private final String[] columns;
 	/** The MonetDB types of the columns in this ResultSet */
@@ -107,11 +108,7 @@ public class MonetResultSet extends Mone
 	 * @param header a header containing the query, resultset type, etc.
 	 * @throws SQLException is a protocol error occurs
 	 */
-	MonetResultSet(
-		Statement statement,
-		MonetConnection.ResultSetResponse header)
-		throws SQLException
-	{
+	MonetResultSet(Statement statement, ResultSetResponse header) throws SQLException {
 		if (statement == null) {
 			throw new IllegalArgumentException("Statement may not be null!");
 		}
@@ -151,13 +148,7 @@ public class MonetResultSet extends Mone
 	 * @param results the number of rows in the ResultSet
 	 * @throws IllegalArgumentException if communicating with monet failed
 	 */
-	MonetResultSet(
-		Statement statement,
-		String[] columns,
-		String[] types,
-		int results
-	) throws IllegalArgumentException
-	{
+	MonetResultSet(Statement statement, String[] columns, String[] types, int results) throws IllegalArgumentException {
 		if (statement == null) {
 			throw new IllegalArgumentException("Statement may not be null!");
 		}
@@ -1792,7 +1783,7 @@ public class MonetResultSet extends Mone
 	 * types. In the JDBC 2.0 API, the behavior of method getObject is extended
 	 * to materialize data of SQL user-defined types. When a column contains a
 	 * structured or distinct value, the behavior of this method is as if it
-	 * were a call to: getObject(columnIndex, this.getStatement().getConnection().getTypeMap()).
+	 * were a call to: getObject(columnIndex, this.getStatement().getInternalConnection().getTypeMap()).
 	 *
 	 * @param columnIndex the first column is 1, the second is 2, ...
 	 * @return a java.lang.Object holding the column value or null
@@ -1964,7 +1955,7 @@ public class MonetResultSet extends Mone
 	 * If Connection.getTypeMap does not throw a SQLFeatureNotSupportedException, then
 	 * when a column contains a structured or distinct value, the behavior of this
 	 * method is as if it were a call to: getObject(columnIndex,
-	 * this.getStatement().getConnection().getTypeMap()).
+	 * this.getStatement().getInternalConnection().getTypeMap()).
 	 * If Connection.getTypeMap does throw a SQLFeatureNotSupportedException, then
 	 * structured values are not supported, and distinct values are mapped to the
 	 * default Java class as determined by the underlying SQL type of the DISTINCT type.
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
@@ -8,6 +8,8 @@
 
 package nl.cwi.monetdb.jdbc;
 
+import nl.cwi.monetdb.responses.*;
+
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.Statement;
@@ -39,7 +41,7 @@ import java.util.concurrent.locks.Reentr
  * which relies on server side auto commit.<br />
  * Multi-result queries are supported using the getMoreResults() method.
  *
- * @author Fabian Groffen
+ * @author Martin van Dinther
  * @version 0.7
  */
 public class MonetStatement extends MonetWrapper implements Statement {
@@ -49,9 +51,9 @@ public class MonetStatement extends Mone
 	/** The parental Connection object */
 	private MonetConnection connection;
 	/** The last ResponseList object this Statement produced */
-	private MonetConnection.ResponseList lastResponseList;
+	private ResponseList lastResponseList;
 	/** The last Response that this object uses */
-	MonetConnection.Response header;
+	IResponse header;
 	/** The warnings this Statement object generated */
 	private SQLWarning warnings;
 	/** Whether this Statement object is closed or not */
@@ -86,13 +88,8 @@ public class MonetStatement extends Mone
 	 * @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
-	{
+	MonetStatement(MonetConnection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+			throws SQLException, IllegalArgumentException {
 		if (connection == null) throw
 			new IllegalArgumentException("No Connection given!");
 
@@ -246,14 +243,7 @@ public class MonetStatement extends Mone
 		}
 	}
 
-	private boolean internalBatch(
-			String batch,
-			int[] counts,
-			int offset,
-			int max,
-			BatchUpdateException e)
-		throws BatchUpdateException
-	{
+	private boolean internalBatch(String batch, int[] counts, int offset, int max, BatchUpdateException e) throws BatchUpdateException {
 		try {
 			boolean type = internalExecute(batch);
 			int count = -1;
@@ -322,7 +312,9 @@ public class MonetStatement extends Mone
 	@Override
 	public void close() {
 		// close previous ResultSet, if not closed already
-		if (lastResponseList != null) lastResponseList.close();
+		if (lastResponseList != null) {
+			lastResponseList.close();
+		}
 		closed = true;
 	}
 
@@ -381,15 +373,11 @@ public class MonetStatement extends Mone
 	 *         Statement.NO_GENERATED_KEYS.
 	 */
 	@Override
-	public boolean execute(String sql, int autoGeneratedKeys)
-		throws SQLException
-	{
-		if (autoGeneratedKeys != Statement.RETURN_GENERATED_KEYS &&
-				autoGeneratedKeys != Statement.NO_GENERATED_KEYS)
+	public boolean execute(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 ;) */
+		}
+		/* MonetDB has no way to disable this, so just do the normal thing ;) */
 		return internalExecute(sql);
 	}
 
@@ -430,10 +418,8 @@ public class MonetStatement extends Mone
 	 *         valid column indexes
 	 */
 	@Override
-	public boolean execute(String sql, int[] columnIndexes)
-		throws SQLException
-	{
-		addWarning("execute: generated keys for fixed set of columns not supported", "01M18");
+	public boolean execute(String sql, int[] columnIndexes) throws SQLException {
+		this.addWarning("execute: generated keys for fixed set of columns not supported", "01M18");
 		return execute(sql, Statement.RETURN_GENERATED_KEYS);
 	}
 
@@ -502,12 +488,7 @@ public class MonetStatement extends Mone
 		}
 
 		// create a container for the result
-		lastResponseList = connection.new ResponseList(
-			fetchSize,
-			maxRows,
-			resultSetType,
-			resultSetConcurrency
-		);
+		lastResponseList = new ResponseList(fetchSize, maxRows, resultSetType, resultSetConcurrency);
 		// fill the header list by processing the query
 		lastResponseList.processQuery(sql);
 
@@ -611,9 +592,7 @@ public class MonetStatement extends Mone
 	 *         whose elements are valid column indexes
 	 */
 	@Override
-	public int executeUpdate(String sql, int[] columnIndexes)
-		throws SQLException
-	{
+	public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
 		addWarning("executeUpdate: generated keys for fixed set of columns not supported", "01M18");
 		return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
 	}
@@ -642,9 +621,7 @@ public class MonetStatement extends Mone
 	 *         whose elements are valid column names
 	 */
 	@Override
-	public int executeUpdate(String sql, String[] columnNames)
-		throws SQLException
-	{
+	public int executeUpdate(String sql, String[] columnNames) throws SQLException {
 		addWarning("executeUpdate: generated keys for fixed set of columns not supported", "01M18");
 		return executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
 	}
@@ -710,8 +687,8 @@ public class MonetStatement extends Mone
 		 * frameworks such as spring expect this. */
 		types[0] = "BIGINT";
 
-		if (header instanceof MonetConnection.UpdateResponse) {
-			String lastid = ((MonetConnection.UpdateResponse)header).lastid;
+		if (header instanceof UpdateResponse) {
+			String lastid = ((UpdateResponse)header).lastid;
 			if (lastid.equals("-1")) {
 				results = new String[0][1];
 			} else {
@@ -742,12 +719,9 @@ public class MonetStatement extends Mone
 	 *
 	 * @return the current column size limit for columns storing
 	 *         character and binary values; zero means there is no limit
-	 * @throws SQLException if a database access error occurs
 	 */
 	@Override
-	public int getMaxFieldSize()
-		throws SQLException
-	{
+	public int getMaxFieldSize() {
 		return 0;
 	}
 
@@ -814,7 +788,7 @@ public class MonetStatement extends Mone
 		// we default to keep current result, which requires no action
 		header = lastResponseList.getNextResponse();
 
-		return header instanceof MonetConnection.ResultSetResponse;
+		return header instanceof ResultSetResponse;
 	}
 
 	/**
@@ -861,9 +835,8 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public ResultSet getResultSet() throws SQLException{
-		return (header instanceof MonetConnection.ResultSetResponse)
-			? new MonetResultSet(this,
-					(MonetConnection.ResultSetResponse)header)
+		return (header instanceof ResultSetResponse)
+			? new MonetResultSet(this, (ResultSetResponse)header)
 			: null;
 	}
 
@@ -916,10 +889,10 @@ public class MonetStatement extends Mone
 	@Override
 	public int getUpdateCount() throws SQLException {
 		int ret = -1;
-		if (header instanceof MonetConnection.UpdateResponse) {
-			ret = ((MonetConnection.UpdateResponse)header).count;
-		} else if (header instanceof MonetConnection.SchemaResponse) {
-			ret = ((MonetConnection.SchemaResponse)header).state;
+		if (header instanceof UpdateResponse) {
+			ret = ((UpdateResponse)header).count;
+		} else if (header instanceof SchemaResponse) {
+			ret = ((SchemaResponse)header).state;
 		}
 
 		return ret;
@@ -942,9 +915,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public SQLWarning getWarnings() throws SQLException {
-		if (closed)
+		if (closed) {
 			throw new SQLException("Cannot call on closed Statement", "M1M20");
-
+		}
 		// if there are no warnings, this will be null, which fits with the
 		// specification.
 		return warnings;
@@ -998,8 +971,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void setEscapeProcessing(boolean enable) throws SQLException {
-		if (enable)
+		if (enable) {
 			addWarning("setEscapeProcessing: JDBC escape syntax is not supported by this driver", "01M22");
+		}
 	}
 
 	/**
@@ -1018,10 +992,7 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void setFetchDirection(int direction) throws SQLException {
-		if (direction == ResultSet.FETCH_FORWARD ||
-		    direction == ResultSet.FETCH_REVERSE ||
-			direction == ResultSet.FETCH_UNKNOWN)
-		{
+		if (direction == ResultSet.FETCH_FORWARD || direction == ResultSet.FETCH_REVERSE || direction == ResultSet.FETCH_UNKNOWN) {
 			fetchDirection = direction;
 		} else {
 			throw new SQLException("Illegal direction: " + direction, "M1M05");
@@ -1066,10 +1037,12 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void setMaxFieldSize(int max) throws SQLException {
-		if (max < 0)
+		if (max < 0) {
 			throw new SQLException("Illegal max value: " + max, "M1M05");
-		if (max > 0)
+		}
+		if (max > 0) {
 			addWarning("setMaxFieldSize: field size limitation not supported", "01M23");
+		}
 	}
 
 	/**
@@ -1082,8 +1055,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void setMaxRows(int max) throws SQLException {
-		if (max < 0)
+		if (max < 0) {
 			throw new SQLException("Illegal max value: " + max, "M1M05");
+		}
 		maxRows = max;
 	}
 
@@ -1099,9 +1073,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void setQueryTimeout(int seconds) throws SQLException {
-		if (seconds < 0)
+		if (seconds < 0) {
 			throw new SQLException("Illegal timeout value: " + seconds, "M1M05");
-
+		}
 		Statement st = null;
 		try {
 			st = connection.createStatement();
@@ -1175,8 +1149,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public void closeOnCompletion() throws SQLException {
-		if (closed)
+		if (closed) {
 			throw new SQLException("Cannot call on closed Statement", "M1M20");
+		}
 		closeOnCompletion = true;
 	}
 
@@ -1190,8 +1165,9 @@ public class MonetStatement extends Mone
 	 */
 	@Override
 	public boolean isCloseOnCompletion() throws SQLException {
-		if (closed)
+		if (closed) {
 			throw new SQLException("Cannot call on closed Statement", "M1M20");
+		}
 		return closeOnCompletion;
 	}
 
@@ -1244,14 +1220,8 @@ final class MonetVirtualResultSet extend
 	private String results[][];
 	private boolean closed;
 
-	MonetVirtualResultSet(
-		Statement statement,
-		String[] columns,
-		String[] types,
-		String[][] results
-	) throws IllegalArgumentException {
+	MonetVirtualResultSet(Statement statement, String[] columns, String[] types, String[][] results) throws IllegalArgumentException {
 		super(statement, columns, types, results.length);
-
 		this.results = results;
 		closed = false;
 	}
@@ -1269,9 +1239,9 @@ final class MonetVirtualResultSet extend
 	 */
 	@Override
 	public boolean absolute(int row) throws SQLException {
-		if (closed)
+		if (closed) {
 			throw new SQLException("ResultSet is closed!", "M1M20");
-
+		}
 		// first calculate what the JDBC row is
 		if (row < 0) {
 			// calculate the negatives...
rename from src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedMonetDB.java
rename to src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedMonetDB.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java
@@ -1,5 +1,6 @@
 package nl.cwi.monetdb.mcl.connection;
 
+import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedConnection;
 import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedDatabase;
 import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedException;
 import nl.cwi.monetdb.jdbc.MonetConnection;
@@ -7,21 +8,29 @@ import nl.cwi.monetdb.mcl.io.*;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 
 import java.io.*;
-import java.net.SocketException;
 import java.util.List;
+import java.util.Properties;
 
 /**
  * Created by ferreira on 11/23/16.
  */
-public final class EmbeddedMonetDB extends MonetConnection {
+public final class EmbeddedConnection extends MonetConnection {
 
     private final String directory;
 
-    private InternalConnection connection;
+    private JDBCEmbeddedConnection internalConnection;
+
+    public EmbeddedConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String directory) throws IOException {
+        super(props, database, hash, language, blobIsBinary, isDebugging);
+        this.directory = directory;
+    }
 
-    public EmbeddedMonetDB(String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String directory) throws IOException {
-        super(database, hash, language, blobIsBinary, isDebugging);
-        this.directory = directory;
+    public String getDirectory() {
+        return directory;
+    }
+
+    public MonetDBEmbeddedConnection getAsMonetDBEmbeddedConnection() {
+        return internalConnection;
     }
 
     @Override
@@ -32,7 +41,7 @@ public final class EmbeddedMonetDB exten
             } else {
                 MonetDBEmbeddedDatabase.StartDatabase(this.directory, true, false);
             }
-            this.connection = MonetDBEmbeddedDatabase.AddJDBCEmbeddedConnection();
+            this.internalConnection = MonetDBEmbeddedDatabase.CreateJDBCEmbeddedConnection();
         } catch (MonetDBEmbeddedException ex) {
             throw new MCLException(ex);
         }
@@ -50,13 +59,14 @@ public final class EmbeddedMonetDB exten
     }
 
     @Override
-    public int getSoTimeout() throws SocketException {
-        throw new SocketException("Cannot get a timeout on a embedded connection!");
+    public int getSoTimeout() {
+        this.addWarning("Cannot get a timeout on a embedded connection!", "M1M05");
+        return -1;
     }
 
     @Override
-    public void setSoTimeout(int s) throws SocketException {
-        throw new SocketException("Cannot set a timeout on a embedded connection!");
+    public void setSoTimeout(int s) {
+        this.addWarning("Cannot set a timeout on a embedded connection!", "M1M05");
     }
 
     @Override
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java
@@ -80,12 +80,32 @@ public class MapiConnection extends Mone
 
     protected OldMapiProtocol protocol;
 
-    public MapiConnection(String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String hostname, int port) throws IOException {
-        super(database, hash, language, blobIsBinary, isDebugging);
+    public MapiConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String hostname, int port) throws IOException {
+        super(props, database, hash, language, blobIsBinary, isDebugging);
         this.hostname = hostname;
         this.port = port;
     }
 
+    public String getHostname() {
+        return hostname;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public boolean isFollowRedirects() {
+        return followRedirects;
+    }
+
+    public int getTtl() {
+        return ttl;
+    }
+
+    public int setProtocolVersion() {
+        return version;
+    }
+
     /**
      * Sets whether MCL redirections should be followed or not.  If set
      * to false, an MCLException will be thrown when a redirect is
@@ -130,13 +150,22 @@ public class MapiConnection extends Mone
     }
 
     @Override
-    public int getSoTimeout() throws SocketException {
-        return protocol.getConnection().getSoTimeout();
+    public int getSoTimeout()  {
+        try {
+            return protocol.getConnection().getSoTimeout();
+        } catch (SocketException e) {
+            this.addWarning("The socket timeout could not be get", "M1M05");
+        }
+        return -1;
     }
 
     @Override
-    public void setSoTimeout(int s) throws SocketException {
-        protocol.getConnection().setSoTimeout(s);
+    public void setSoTimeout(int s)  {
+        try {
+            protocol.getConnection().setSoTimeout(s);
+        } catch (SocketException e) {
+            this.addWarning("The socket timeout could not be set", "M1M05");
+        }
     }
 
     @Override
@@ -147,7 +176,7 @@ public class MapiConnection extends Mone
     @Override
     public String getJDBCURL() {
         String language = "";
-        if (this.getCurrentMonetDBLanguage() == MonetDBLanguage.LANG_MAL)
+        if (this.getLanguage() == MonetDBLanguage.LANG_MAL)
             language = "?language=mal";
         return "jdbc:monetdb://" + this.hostname + ":" + this.port + "/" + this.database + language;
     }
@@ -178,7 +207,7 @@ public class MapiConnection extends Mone
 
         this.protocol.getNextResponseHeader();
         String test = this.getChallengeResponse(this.protocol.getEntireResponseLine(), user, pass,
-                this.currentMonetDBLanguage.getRepresentation(), this.database, this.hash);
+                this.language.getRepresentation(), this.database, this.hash);
         this.protocol.writeNextLine(test.getBytes());
 
         List<String> redirects = new ArrayList<>();
@@ -243,7 +272,7 @@ public class MapiConnection extends Mone
                                 case "language":
                                     tmp = arg.substring(pos + 1);
                                     warns.add("redirect specifies use of different language: " + tmp);
-                                     this.currentMonetDBLanguage = MonetDBLanguage.GetLanguageFromString(tmp);
+                                     this.language = MonetDBLanguage.GetLanguageFromString(tmp);
                                     break;
                                 case "user":
                                     tmp = arg.substring(pos + 1);
@@ -432,6 +461,10 @@ public class MapiConnection extends Mone
                 response += username + ":" + pwhash + ":" + language;
                 response += ":" + (database == null ? "" : database) + ":";
 
+                this.conn_props.setProperty("hash", hashes);
+                this.conn_props.setProperty("language", language);
+                this.conn_props.setProperty("database", database);
+
                 return response;
         }
     }
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java
@@ -1,11 +1,11 @@
 package nl.cwi.monetdb.mcl.connection;
 
 import nl.cwi.monetdb.jdbc.MonetConnection;
+import nl.cwi.monetdb.jdbc.MonetDriver;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.SocketException;
 import java.sql.SQLException;
 import java.util.Calendar;
 import java.util.List;
@@ -38,7 +38,7 @@ public final class MonetDBConnectionFact
             if (directory == null || directory.trim().isEmpty())
                 throw new IllegalArgumentException("directory should not be null or empty");
             try {
-                res = new EmbeddedMonetDB(database, hash, language, blobIsBinary, debug, directory);
+                res = new EmbeddedConnection(props, database, hash, language, blobIsBinary, debug, directory);
             } catch (IOException e) {
                 throw new SQLException(e);
             }
@@ -46,40 +46,60 @@ public final class MonetDBConnectionFact
             String hostname = props.getProperty("host");
             if (hostname == null || hostname.trim().isEmpty())
                 throw new IllegalArgumentException("hostname should not be null or empty");
-            int port = 0;
-            try {
-                port = Integer.parseInt(props.getProperty("port"));
-            } catch (NumberFormatException e) {
-            }
-            if (port <= 0)
-                throw new IllegalArgumentException("port should not be 0 or less");
             if (username == null || username.trim().isEmpty())
                 throw new IllegalArgumentException("user should not be null or empty");
             if (password == null || password.trim().isEmpty())
                 throw new IllegalArgumentException("password should not be null or empty");
 
+            String portout = props.getProperty("portout");
+            boolean negative1 = false;
+            boolean failedparse1 = false;
+            int port = 0;
             try {
-                res = new MapiConnection(database, hash, language, blobIsBinary, debug, hostname, port);
-            } catch (IOException e) {
-                throw new SQLException(e);
+                port = Integer.parseInt(props.getProperty("port"));
+            } catch (NumberFormatException e) {
+                failedparse1 = true;
+                props.setProperty("port", MonetDriver.getPORT());
             }
+            if (port <= 0) {
+                negative1 = true;
+                port = Integer.parseInt(MonetDriver.getPORT());
+                props.setProperty("port", MonetDriver.getPORT());
+            }
+
             String timout = props.getProperty("so_timeout", "0");
+            boolean negative2 = false;
+            boolean failedparse2 = false;
             try {
                 sockTimeout = Integer.parseInt(timout);
             } catch (NumberFormatException e) {
-                res.addWarning("Unable to parse socket timeout number from: " + timout, "M1M05");
+                failedparse2 = true;
+                props.setProperty("so_timeout", "0");
             }
             if (sockTimeout < 0) {
-                res.addWarning("Negative socket timeout not allowed. Value ignored", "M1M05");
+                negative2 = true;
                 sockTimeout = 0;
+                props.setProperty("so_timeout", "0");
             }
             try {
-                res.setSoTimeout(sockTimeout);
-            } catch (SocketException e) {
-                res.addWarning("The socket timeout could not be set", "M1M05");
+                res = new MapiConnection(props, database, hash, language, blobIsBinary, debug, hostname, port);
+            } catch (IOException e) {
+                throw new SQLException(e);
+            }
+            if(failedparse1) {
+                res.addWarning("Unable to parse port number from: " + portout, "M1M05");
             }
+            if(negative1) {
+                res.addWarning("Negative port not allowed. Value ignored", "M1M05");
+            }
+            if(failedparse2) {
+                res.addWarning("Unable to parse socket timeout number from: " + timout, "M1M05");
+            }
+            if(negative2) {
+                res.addWarning("Negative socket timeout not allowed. Value ignored", "M1M05");
+            }
+            res.setSoTimeout(sockTimeout);
         }
-
         //initialize the debugging stuff if so
         if (debug) {
             try {
@@ -100,25 +120,24 @@ public final class MonetDBConnectionFact
 
         try {
             List<String> warnings = res.connect(username, password);
-            for (String warning : warnings) {
-                res.addWarning(warning, "01M02");
+            if(warnings != null) {
+                for (String warning : warnings) {
+                    res.addWarning(warning, "01M02");
+                }
             }
-
             // apply NetworkTimeout value from legacy (pre 4.1) driver
             // so_timeout calls
             if(!isEmbedded) {
                 res.setSoTimeout(sockTimeout);
             }
-
-
-            in = server.getReader();
-            out = server.getWriter();
-
-            String error = in.waitForPrompt();
-            if (error != null)
-                throw new SQLException((error.length() > 6) ? error.substring(6) : error, "08001");
         } catch (IOException e) {
-            throw new SQLException("Unable to connect (" + hostname + ":" + port + "): " + e.getMessage(), "08006");
+            if(!isEmbedded) {
+                MapiConnection con = (MapiConnection) res;
+                throw new SQLException("Unable to connect (" + con.getHostname() + ":" + con.getPort() + "): " + e.getMessage(), "08006");
+            } else {
+                EmbeddedConnection em = (EmbeddedConnection) res;
+                throw new SQLException("Unable to connect the directory " + em.getDirectory() + ": " + e.getMessage(), "08006");
+            }
         } catch (MCLParseException e) {
             throw new SQLException(e.getMessage(), "08001");
         } catch (MCLException e) {
@@ -130,7 +149,8 @@ public final class MonetDBConnectionFact
             throw sqle;
         }
 
-        if (res.getCurrentMonetDBLanguage() == MonetDBLanguage.LANG_SQL) {
+        //set the timezone
+        if (res.getLanguage() == MonetDBLanguage.LANG_SQL) {
             // enable auto commit
             res.setAutoCommit(true);
 
rename from src/main/java/nl/cwi/monetdb/responses/SendThread.java
rename to src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java
--- a/src/main/java/nl/cwi/monetdb/responses/SendThread.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java
@@ -1,4 +1,4 @@
-package nl.cwi.monetdb.responses;
+package nl.cwi.monetdb.mcl.connection;
 
 import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
 
@@ -20,19 +20,21 @@ import java.util.concurrent.locks.Reentr
  * high.
  */
 public class SendThread extends Thread {
-    /** The state WAIT represents this thread to be waiting for
-     *  something to do */
-    private final static int WAIT = 0;
-    /** The state QUERY represents this thread to be executing a query */
-    private final static int QUERY = 1;
-    /** The state SHUTDOWN is the final state that ends this thread */
-    private final static int SHUTDOWN = -1;
+
+    private enum SendThreadStatus {
+        /** The state WAIT represents this thread to be waiting for something to do */
+        WAIT,
+        /** The state QUERY represents this thread to be executing a query */
+        QUERY,
+        /** The state SHUTDOWN is the final state that ends this thread */
+        SHUTDOWN
+    }
 
     private String[] templ;
     private String query;
     private AbstractMCLWriter out;
     private String error;
-    private int state = WAIT;
+    private SendThreadStatus state = SendThreadStatus.WAIT;
 
     private final Lock sendLock = new ReentrantLock();
     private final Condition queryAvailable = sendLock.newCondition();
@@ -56,14 +58,14 @@ public class SendThread extends Thread {
         sendLock.lock();
         try {
             while (true) {
-                while (state == WAIT) {
+                while (state == SendThreadStatus.WAIT) {
                     try {
                         queryAvailable.await();
                     } catch (InterruptedException e) {
                         // woken up, eh?
                     }
                 }
-                if (state == SHUTDOWN)
+                if (state == SendThreadStatus.SHUTDOWN)
                     break;
 
                 // state is QUERY here
@@ -75,7 +77,7 @@ public class SendThread extends Thread {
 
                 // update our state, and notify, maybe someone is waiting
                 // for us in throwErrors
-                state = WAIT;
+                state = SendThreadStatus.WAIT;
                 waiting.signal();
             }
         } finally {
@@ -95,14 +97,14 @@ public class SendThread extends Thread {
     public void runQuery(String[] templ, String query) throws SQLException {
         sendLock.lock();
         try {
-            if (state != WAIT)
+            if (state != SendThreadStatus.WAIT)
                 throw new SQLException("SendThread already in use or shutting down!", "M0M03");
 
             this.templ = templ;
             this.query = query;
 
             // let the thread know there is some work to do
-            state = QUERY;
+            state = SendThreadStatus.QUERY;
             queryAvailable.signal();
         } finally {
             sendLock.unlock();
@@ -118,14 +120,14 @@ public class SendThread extends Thread {
         sendLock.lock();
         try {
             // make sure the thread is in WAIT state, not QUERY
-            while (state == QUERY) {
+            while (state == SendThreadStatus.QUERY) {
                 try {
                     waiting.await();
                 } catch (InterruptedException e) {
                     // just try again
                 }
             }
-            if (state == SHUTDOWN)
+            if (state == SendThreadStatus.SHUTDOWN)
                 error = "SendThread is shutting down";
         } finally {
             sendLock.unlock();
@@ -138,7 +140,7 @@ public class SendThread extends Thread {
      */
     public void shutdown() {
         sendLock.lock();
-        state = SHUTDOWN;
+        state = SendThreadStatus.SHUTDOWN;
         sendLock.unlock();
         this.interrupt();  // break any wait conditions
     }
--- a/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java
@@ -8,8 +8,6 @@
 
 package nl.cwi.monetdb.mcl.io;
 
-import nl.cwi.monetdb.mcl.connection.DeleteMe;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -39,7 +37,6 @@ import java.io.UnsupportedEncodingExcept
  * messages as the server receives them.
  *
  * @author Fabian Groffen <Fabian.Groffen>
- * @see DeleteMe
  * @see BufferedMCLWriter
  */
 public class BufferedMCLReader extends AbstractMCLReader {
--- a/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java
@@ -8,8 +8,6 @@
 
 package nl.cwi.monetdb.mcl.io;
 
-import nl.cwi.monetdb.mcl.connection.DeleteMe;
-
 import java.io.*;
 
 /**
@@ -30,7 +28,6 @@ import java.io.*;
  * class client-oriented when a reader is registered.
  *
  * @author Fabian Groffen <Fabian.Groffen>
- * @see DeleteMe
  * @see BufferedMCLWriter
  */
 public class BufferedMCLWriter extends AbstractMCLWriter {
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package nl.cwi.monetdb.mcl.io;
-
-import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB;
-
-import java.io.*;
-
-/**
- * Created by ferreira on 11/24/16.
- */
-public final class EmbeddedMCLReader extends AbstractMCLReader {
-
-    private final EmbeddedMonetDB connection;
-
-    private int readerCurrentPos;
-
-    private final int[] responseHeaderValues = new int[4];
-
-    private String nextLine = "";
-
-    public EmbeddedMCLReader(EmbeddedMonetDB connection) {
-        super(null);
-        this.connection = connection;
-    }
-
-    @Override
-    public String readLine() throws IOException {
-        this.lineType = this.responseHeaderValues[this.readerCurrentPos];
-        this.readerCurrentPos++;
-
-        String res = this.nextLine; //this readline will never wait!!
-
-        if (this.lineType == ERROR && !res.matches("^![0-9A-Z]{5}!.+"))
-            res = "!22000!" + res.substring(1);
-        return res;
-    }
-
-    @Override
-    public synchronized String waitForPrompt() throws IOException {
-        try {
-            this.wait(); //must mimic the socket readline with the wait/notify methods
-        } catch (InterruptedException e) {
-            throw new IOException(e);
-        }
-        return null;
-    }
-}
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package nl.cwi.monetdb.mcl.io;
-
-import nl.cwi.monetdb.mcl.connection.EmbeddedMonetDB;
-import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedHeaderLineParser;
-import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedStartOfHeaderParser;
-import nl.cwi.monetdb.mcl.parser.embedded.EmbeddedTupleLineParser;
-
-import java.io.*;
-
-/**
- * Created by ferreira on 11/24/16.
- */
-public final class EmbeddedMCLWriter extends AbstractMCLWriter {
-
-    private final EmbeddedMonetDB connection;
-
-    private final EmbeddedStartOfHeaderParser sohp;
-
-    private EmbeddedHeaderLineParser nexthlp;
-
-    private EmbeddedTupleLineParser nexttlp;
-
-    public void setNexthlp(EmbeddedHeaderLineParser nexthlp) {
-        this.nexthlp = nexthlp;
-    }
-
-    public void setNexttlp(EmbeddedTupleLineParser nexttlp) {
-        this.nexttlp = nexttlp;
-    }
-
-    public EmbeddedMCLWriter(EmbeddedMonetDB con, EmbeddedMCLReader reader, EmbeddedStartOfHeaderParser sohp) {
-        super(null);
-        this.connection = con;
-        this.reader = reader;
-        this.sohp = sohp;
-    }
-
-    @Override
-    public void writeLine(String line) throws IOException {
-        this.reader.notify(); //wake up the embedded reader.
-    }
-
-}
rename from src/main/java/nl/cwi/monetdb/mcl/io/InternalConnection.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/JDBCEmbeddedConnection.java
--- a/src/main/java/nl/cwi/monetdb/mcl/io/InternalConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/JDBCEmbeddedConnection.java
@@ -1,27 +1,13 @@
 package nl.cwi.monetdb.mcl.io;
 
-import nl.cwi.monetdb.embedded.env.IEmbeddedConnection;
+import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedConnection;
 
 /**
- * Created by ferreira on 11/30/16.
+ * Created by ferreira on 12/1/16.
  */
-public class InternalConnection implements IEmbeddedConnection {
-
-    private long connectionPointer;
-
-    public InternalConnection(long connectionPointer) {
-        this.connectionPointer = connectionPointer;
-    }
+public class JDBCEmbeddedConnection extends MonetDBEmbeddedConnection {
 
-    @Override
-    public long getConnectionPointer() {
-        return this.connectionPointer;
+    protected JDBCEmbeddedConnection(long connectionPointer) {
+        super(connectionPointer);
     }
-
-    @Override
-    public void closeConnectionImplementation() {
-        this.closeConnectionInternal(this.connectionPointer);
-    }
-
-    private native void closeConnectionInternal(long connectionPointer);
 }
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedHeaderLineParser.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package nl.cwi.monetdb.mcl.parser.embedded;
-
-import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
-import nl.cwi.monetdb.mcl.parser.MCLParseException;
-
-/**
- * Created by ferreira on 11/25/16.
- */
-public class EmbeddedHeaderLineParser extends HeaderLineParser {
-
-    private long resultSetPointer;
-
-    /**
-     * Creates an MCLParser targeted at a given number of field values.
-     * The lines parsed by an instance of this MCLParser should have
-     * exactly capacity field values.
-     *
-     * @param capacity the number of field values to expect
-     */
-    public EmbeddedHeaderLineParser(int capacity) {
-        super(capacity);
-    }
-
-    @Override
-    public int parse(String source) throws MCLParseException {
-        /*switch(this.colnr) {
-            case HeaderLineParser.NAME:
-                System.arraycopy(this.columnNames, 0, this.values, 0, this.values.length);
-                break;
-            case HeaderLineParser.LENGTH:
-                System.arraycopy(this.columnLengths, 0, this.intValues, 0, this.intValues.length);
-                break;
-            case HeaderLineParser.TABLE:
-                System.arraycopy(this.columnTables, 0, this.values, 0, this.values.length);
-                break;
-            case HeaderLineParser.TYPE:
-                System.arraycopy(this.columnTypes, 0, this.values, 0, this.values.length);
-                break;
-        }*/
-        return this.parseNextHeadLineInternal();
-    }
-
-    private native int parseNextHeadLineInternal();
-}
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedStartOfHeaderParser.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package nl.cwi.monetdb.mcl.parser.embedded;
-
-import nl.cwi.monetdb.mcl.parser.MCLParseException;
-import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
-
-/**
- * Created by ferreira on 11/25/16.
- */
-public class EmbeddedStartOfHeaderParser extends StartOfHeaderParser {
-
-    private int nextResponseType;
-
-    private final int[] nextIntValues = new int[4];
-
-    private String nextStringValue;
-
-    @Override
-    public int parse(String in) throws MCLParseException {
-        this.pos = 0;
-        switch (this.nextResponseType) {
-            /*case Q_PARSE:*/
-            case Q_SCHEMA:
-                this.len = 0;
-                break;
-            case Q_TABLE:
-            case Q_PREPARE:
-                this.len = 4;
-                break;
-            case Q_UPDATE:
-                this.len = 2;
-                break;
-            case Q_TRANS:
-                this.len = 1;
-                break;
-            /*case Q_BLOCK:
-                len = 3;
-                break;*/
-            default:
-                throw new MCLParseException("invalid or unknown header", 1);
-        }
-        return this.nextResponseType;
-    }
-
-    @Override
-    public int getNextAsInt() throws MCLParseException {
-        int res = this.nextIntValues[this.pos];
-        this.pos++;
-        return res;
-    }
-
-    @Override
-    public String getNextAsString() throws MCLParseException {
-        return this.nextStringValue;
-    }
-}
deleted file mode 100644
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedTupleLineParser.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package nl.cwi.monetdb.mcl.parser.embedded;
-
-import nl.cwi.monetdb.mcl.parser.MCLParseException;
-import nl.cwi.monetdb.mcl.parser.TupleLineParser;
-
-/**
- * Created by ferreira on 11/25/16.
- */
-public class EmbeddedTupleLineParser extends TupleLineParser {
-
-    /**
-     * Creates an MCLParser targeted at a given number of field values.
-     * The lines parsed by an instance of this MCLParser should have
-     * exactly capacity field values.
-     *
-     * @param capacity the number of field values to expect
-     */
-    public EmbeddedTupleLineParser(int capacity) {
-        super(capacity);
-    }
-
-    @Override
-    public int parse(String source) throws MCLParseException {
-        return 0;
-    }
-}
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java
@@ -1,6 +1,6 @@
 package nl.cwi.monetdb.mcl.protocol.embedded;
 
-import nl.cwi.monetdb.mcl.io.InternalConnection;
+import nl.cwi.monetdb.mcl.io.JDBCEmbeddedConnection;
 import nl.cwi.monetdb.mcl.protocol.AbstractProtocolParser;
 import nl.cwi.monetdb.mcl.protocol.ServerResponses;
 import nl.cwi.monetdb.mcl.protocol.StarterHeaders;
@@ -11,9 +11,9 @@ import nl.cwi.monetdb.mcl.protocol.Table
  */
 public class EmbeddedProtocol extends AbstractProtocolParser {
 
-    private final InternalConnection embeddedConnection;
+    private final JDBCEmbeddedConnection embeddedConnection;
 
-    public EmbeddedProtocol(InternalConnection embeddedConnection) {
+    public EmbeddedProtocol(JDBCEmbeddedConnection embeddedConnection) {
         this.embeddedConnection = embeddedConnection;
     }
 
--- a/src/main/java/nl/cwi/monetdb/responses/AutoCommitResponse.java
+++ b/src/main/java/nl/cwi/monetdb/responses/AutoCommitResponse.java
@@ -6,6 +6,7 @@ package nl.cwi.monetdb.responses;
  * <tt>&amp;4 (t|f)</tt>
  */
 public class AutoCommitResponse extends SchemaResponse {
+
     public final boolean autocommit;
 
     public AutoCommitResponse(boolean ac) {
--- a/src/main/java/nl/cwi/monetdb/responses/ResponseList.java
+++ b/src/main/java/nl/cwi/monetdb/responses/ResponseList.java
@@ -1,6 +1,7 @@
 package nl.cwi.monetdb.responses;
 
 import nl.cwi.monetdb.jdbc.MonetConnection;
+import nl.cwi.monetdb.mcl.connection.SendThread;
 import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
@@ -38,13 +39,12 @@ public class ResponseList {
     private final int seqnr;
     /** A list of the Responses associated with the query,
      *  in the right order */
-    private List<IResponse> responses;
+    private 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;
+    private int curResponse = -1;
 
     /**
      * Main constructor.  The query argument can either be a String
@@ -61,9 +61,7 @@ public class ResponseList {
         this.maxrows = maxrows;
         this.rstype = rstype;
         this.rsconcur = rsconcur;
-        responses = new ArrayList<>();
-        curResponse = -1;
-        seqnr = SeqCounter++;
+        this.seqnr = SeqCounter++;
     }
 
     /**
@@ -107,14 +105,14 @@ public class ResponseList {
     /**
      * Closes the current response.
      */
-    void closeCurrentResponse() {
+    public void closeCurrentResponse() {
         closeResponse(curResponse);
     }
 
     /**
      * Closes the current and previous responses.
      */
-    void closeCurOldResponses() {
+    public void closeCurOldResponses() {
         for (int i = curResponse; i >= 0; i--) {
             closeResponse(i);
         }
@@ -134,7 +132,7 @@ public class ResponseList {
      * Returns whether this ResponseList has still unclosed
      * Responses.
      */
-    boolean hasUnclosedResponses() {
+    public boolean hasUnclosedResponses() {
         for (IResponse r : responses) {
             if (r != null)
                 return true;
--- a/src/main/java/nl/cwi/monetdb/responses/ResultSetResponse.java
+++ b/src/main/java/nl/cwi/monetdb/responses/ResultSetResponse.java
@@ -206,7 +206,7 @@ public class ResultSetResponse implement
      * @param offset the offset number of rows for this block
      * @param rr the DataBlockResponse to add
      */
-    void addDataBlockResponse(int offset, DataBlockResponse rr) {
+    public void addDataBlockResponse(int offset, DataBlockResponse rr) {
         int block = (offset - blockOffset) / cacheSize;
         resultBlocks[block] = rr;
     }
@@ -233,7 +233,7 @@ public class ResultSetResponse implement
      *
      * @return the names of the columns
      */
-    String[] getNames() {
+    public String[] getNames() {
         return name;
     }
 
@@ -242,7 +242,7 @@ public class ResultSetResponse implement
      *
      * @return the types of the columns
      */
-    String[] getTypes() {
+    public String[] getTypes() {
         return type;
     }
 
@@ -251,7 +251,7 @@ public class ResultSetResponse implement
      *
      * @return the tables of the columns
      */
-    String[] getTableNames() {
+    public String[] getTableNames() {
         return tableNames;
     }
 
@@ -260,7 +260,7 @@ public class ResultSetResponse implement
      *
      * @return the lengths of the columns
      */
-    int[] getColumnLengths() {
+    public int[] getColumnLengths() {
         return columnLengths;
     }
 
@@ -269,7 +269,7 @@ public class ResultSetResponse implement
      *
      * @return the cache size
      */
-    int getCacheSize() {
+    public int getCacheSize() {
         return cacheSize;
     }
 
@@ -278,7 +278,7 @@ public class ResultSetResponse implement
      *
      * @return the current block offset
      */
-    int getBlockOffset() {
+    public int getBlockOffset() {
         return blockOffset;
     }
 
@@ -287,7 +287,7 @@ public class ResultSetResponse implement
      *
      * @return the ResultSet type
      */
-    int getRSType() {
+    public int getRSType() {
         return parent.rstype;
     }
 
@@ -296,7 +296,7 @@ public class ResultSetResponse implement
      *
      * @return the ResultSet concurrency
      */
-    int getRSConcur() {
+    public int getRSConcur() {
         return parent.rsconcur;
     }
 
@@ -311,7 +311,7 @@ public class ResultSetResponse implement
      *         is out of the scope of the result set
      * @throws SQLException if an database error occurs
      */
-    String getLine(int row) throws SQLException {
+    public String getLine(int row) throws SQLException {
         if (row >= tuplecount || row < 0)
             return null;
 
@@ -403,7 +403,7 @@ public class ResultSetResponse implement
      *
      * @return whether this Response is closed
      */
-    boolean isClosed() {
+    public boolean isClosed() {
         return closed;
     }
 }