changeset 62:b66003555560 embedded

Split parsers and cleaned the MCL layer.
author Pedro Ferreira <pedro.ferreira@monetdbsolutions.com>
date Fri, 25 Nov 2016 12:05:10 +0100 (2016-11-25)
parents f1de7262d8d9
children 6325594f01af
files example/SQLcopyinto.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/MonetResultSet.java src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedReader.java src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedWriter.java src/main/java/nl/cwi/monetdb/mcl/connection/AbstractMonetDBConnection.java src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedConnection.java src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedReader.java src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedWriter.java src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLReader.java src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLWriter.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/net/AbstractMCLConnection.java src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLReader.java src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLWriter.java src/main/java/nl/cwi/monetdb/mcl/net/EmbeddedMonetDB.java src/main/java/nl/cwi/monetdb/mcl/net/MapiSocket.java src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java src/main/java/nl/cwi/monetdb/mcl/parser/MCLParser.java src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.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/parser/socket/SocketHeaderLineParser.java src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketStartOfHeaderParser.java src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketTupleLineParser.java src/main/java/nl/cwi/monetdb/merovingian/Control.java src/main/java/nl/cwi/monetdb/util/SQLRestore.java
diffstat 34 files changed, 1586 insertions(+), 1388 deletions(-) [+]
line wrap: on
line diff
--- a/example/SQLcopyinto.java
+++ b/example/SQLcopyinto.java
@@ -10,8 +10,8 @@ import java.sql.*;
 import java.io.*;
 import java.util.*;
 
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
 import nl.cwi.monetdb.mcl.net.*;
 
 /**
@@ -61,8 +61,8 @@ public class SQLcopyinto {
 				}
 			}
 
-			AbstractBufferedReader in = server.getReader();
-			AbstractBufferedWriter out = server.getWriter();
+			AbstractMCLReader in = server.getReader();
+			AbstractMCLWriter out = server.getWriter();
 
 			String error = in.waitForPrompt();
 			if (error != null)
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java
+++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedDatabase.java
@@ -8,7 +8,7 @@
 
 package nl.cwi.monetdb.embedded.env;
 
-import nl.cwi.monetdb.mcl.embedded.EmbeddedConnection;
+import nl.cwi.monetdb.mcl.net.EmbeddedMonetDB;
 
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -172,7 +172,7 @@ public class MonetDBEmbeddedDatabase {
         return CompletableFuture.supplyAsync(() -> this.createConnectionInternal());
     }*/
 
-    public static void AddJDBCEmbeddedConnection(EmbeddedConnection con) throws MonetDBEmbeddedException {
+    public static void AddJDBCEmbeddedConnection(EmbeddedMonetDB con) throws MonetDBEmbeddedException {
         if(MonetDBEmbeddedDatabase == null) {
             throw new MonetDBEmbeddedException("The database is not running!");
         } else {
@@ -208,5 +208,5 @@ public class MonetDBEmbeddedDatabase {
     /**
      * Internal implementation to create a JDBC embeddded connection on this database.
      */
-    private native void createJDBCConnectionInternal(EmbeddedConnection emc) throws MonetDBEmbeddedException;
+    private native void createJDBCConnectionInternal(EmbeddedMonetDB emc) throws MonetDBEmbeddedException;
 }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -44,14 +44,14 @@ import java.util.concurrent.locks.Reentr
 import nl.cwi.monetdb.jdbc.types.INET;
 import nl.cwi.monetdb.jdbc.types.URL;
 import nl.cwi.monetdb.mcl.MCLException;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
-import nl.cwi.monetdb.mcl.embedded.EmbeddedConnection;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
+import nl.cwi.monetdb.mcl.net.EmbeddedMonetDB;
 import nl.cwi.monetdb.mcl.net.MapiSocket;
-import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection;
+import nl.cwi.monetdb.mcl.net.AbstractMCLConnection;
 import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
+import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
-import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
 
 /**
  * A {@link Connection} suitable for the MonetDB database.
@@ -81,14 +81,13 @@ import nl.cwi.monetdb.mcl.parser.StartOf
 public class MonetConnection extends MonetWrapper implements Connection {
 
 	/** A connection to mserver5 either through MAPI with TCP or embedded */
-	private final AbstractMonetDBConnection server;
+	private final AbstractMCLConnection server;
 	/** The Reader from the server */
-	private final AbstractBufferedReader in;
+	private final AbstractMCLReader in;
 	/** The Writer to the server */
-	private final AbstractBufferedWriter out;
-
-	/** A StartOfHeaderParser  declared for reuse. */
-	private StartOfHeaderParser sohp = new StartOfHeaderParser();
+	private final AbstractMCLWriter out;
+	/** A StartOfHeaderParser declared for reuse. */
+	private final StartOfHeaderParser sohp;
 
 	/** Whether this Connection is closed (and cannot be used anymore) */
 	private boolean closed;
@@ -150,7 +149,7 @@ public class MonetConnection extends Mon
 			if (directory == null || directory.trim().isEmpty())
 				throw new IllegalArgumentException("directory should not be null or empty");
 
-			server = new EmbeddedConnection("localhost", -1, database, username, debug, "sql", null, directory);
+			server = new EmbeddedMonetDB("localhost", -1, database, username, debug, "sql", null, directory);
 		} else {
 			String hostname = props.getProperty("host");
 			String hash = props.getProperty("hash");
@@ -220,9 +219,11 @@ public class MonetConnection extends Mon
 
 			in = server.getReader();
 			out = server.getWriter();
-			String error = in.waitForPrompt(); //TODO CHECK THIS
+			String error = in.waitForPrompt();
 			if (error != null)
 				throw new SQLException(error.substring(6), "08001");
+
+			sohp = server.getStartOfHeaderParser();
 		} catch (IOException e) {
 			throw new SQLException("Unable to connect (" + server.getHostname() + ":" + server.getPort() + "): " + e.getMessage(), "08006");
 		} catch (MCLParseException e) {
@@ -238,7 +239,7 @@ public class MonetConnection extends Mon
 
 		// the following initialisers are only valid when the language
 		// is SQL...
-		if (server.getLang() == AbstractMonetDBConnection.LANG_SQL) {
+		if (server.getLang() == AbstractMCLConnection.LANG_SQL) {
 			// enable auto commit
 			setAutoCommit(true);
 			// set our time zone on the server
@@ -253,7 +254,7 @@ public class MonetConnection extends Mon
 		}
 	}
 
-	protected AbstractMonetDBConnection getServer() {
+	protected AbstractMCLConnection getServer() {
 		return server;
 	}
 
@@ -626,7 +627,7 @@ public class MonetConnection extends Mon
 	 */
 	@Override
 	public DatabaseMetaData getMetaData() throws SQLException {
-		if (server.getLang() != AbstractMonetDBConnection.LANG_SQL)
+		if (server.getLang() != AbstractMCLConnection.LANG_SQL)
 			throw new SQLException("This method is only supported in SQL mode", "M0M04");
 
 		return new MonetDatabaseMetaData(this);
@@ -1634,7 +1635,7 @@ public class MonetConnection extends Mon
 			this.resultBlocks =
 				new DataBlockResponse[(tuplecount / cacheSize) + 1];
 
-			hlp = new HeaderLineParser(columncount);
+			hlp = server.getHeaderLineParser(columncount);
 
 			resultBlocks[0] = new DataBlockResponse(
 				rowcount,
@@ -1658,7 +1659,7 @@ public class MonetConnection extends Mon
 				return resultBlocks[0].addLine(tmpLine, linetype);
 			}
 
-			if (linetype != AbstractBufferedReader.HEADER)
+			if (linetype != AbstractMCLReader.HEADER)
 				return "header expected, got: " + tmpLine;
 
 			// depending on the name of the header, we continue
@@ -1992,7 +1993,7 @@ public class MonetConnection extends Mon
 		 */
 		@Override
 		public String addLine(String line, int linetype) {
-			if (linetype != AbstractBufferedReader.RESULT)
+			if (linetype != AbstractMCLReader.RESULT)
 				return "protocol violation: unexpected line in data block: " + line;
 			// add to the backing array
 			data[++pos] = line;
@@ -2321,7 +2322,7 @@ public class MonetConnection extends Mon
 					int size = cachesize == 0 ? DEF_FETCHSIZE : cachesize;
 					size = maxrows != 0 ? Math.min(maxrows, size) : size;
 					// don't do work if it's not needed
-					if (server.getLang() == AbstractMonetDBConnection.LANG_SQL && size != curReplySize && templ != server.getCommandHeaderTemplates()) {
+					if (server.getLang() == AbstractMCLConnection.LANG_SQL && size != curReplySize && templ != server.getCommandHeaderTemplates()) {
 						sendControlCommand("reply_size " + size);
 
 						// store the reply size after a successful change
@@ -2354,11 +2355,11 @@ public class MonetConnection extends Mon
 					String tmpLine = in.readLine();
 					int linetype = in.getLineType();
 					Response res = null;
-					while (linetype != AbstractBufferedReader.PROMPT) {
+					while (linetype != AbstractMCLReader.PROMPT) {
 						// each response should start with a start of header
 						// (or error)
 						switch (linetype) {
-							case AbstractBufferedReader.SOHEADER:
+							case AbstractMCLReader.SOHEADER:
 								// make the response object, and fill it
 								try {
 									switch (sohp.parse(tmpLine)) {
@@ -2487,7 +2488,7 @@ public class MonetConnection extends Mon
 								tmpLine = in.readLine();
 								linetype = in.getLineType();
 							break;
-							case AbstractBufferedReader.INFO:
+							case AbstractMCLReader.INFO:
 								addWarning(tmpLine.substring(1), "01000");
 
 								// read the next line (can be prompt, new
@@ -2502,7 +2503,7 @@ public class MonetConnection extends Mon
 								// message
 								tmpLine = "!M0M10!protocol violation, unexpected line: " + tmpLine;
 								// don't break; fall through...
-							case AbstractBufferedReader.ERROR:
+							case AbstractMCLReader.ERROR:
 								// read everything till the prompt (should be
 								// error) we don't know if we ignore some
 								// garbage here... but the log should reveal
@@ -2579,7 +2580,7 @@ public class MonetConnection extends Mon
 
 		private String[] templ;
 		private String query;
-		private AbstractBufferedWriter out;
+		private AbstractMCLWriter out;
 		private String error;
 		private int state = WAIT;
 		
@@ -2593,7 +2594,7 @@ public class MonetConnection extends Mon
 		 *
 		 * @param out the socket to write to
 		 */
-		public SendThread(AbstractBufferedWriter out) {
+		public SendThread(AbstractMCLWriter out) {
 			super("SendThread");
 			setDaemon(true);
 			this.out = out;
--- 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 java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.Reader;
@@ -134,7 +135,7 @@ public class MonetResultSet extends Mone
 		tupleCount = header.tuplecount;
 
 		// create result array
-		tlp = new TupleLineParser(columns.length);
+		tlp = ((MonetConnection)statement.getConnection()).getServer().getTupleLineParser(columns.length);
 
 		JdbcSQLTypes = new int[types.length];
 		populateJdbcSQLtypesArray();
@@ -178,7 +179,11 @@ public class MonetResultSet extends Mone
 		this.types = types;
 		this.tupleCount = results;
 
-		this.tlp = new TupleLineParser(columns.length);
+		try {
+			this.tlp = ((MonetConnection)statement.getConnection()).getServer().getTupleLineParser(columns.length);
+		} catch (SQLException e) {
+			throw new IllegalArgumentException(e);
+		}
 
 		JdbcSQLTypes = new int[types.length];
 		populateJdbcSQLtypesArray();
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
@@ -8,7 +8,7 @@
 
 package nl.cwi.monetdb.jdbc;
 
-import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection;
+import nl.cwi.monetdb.mcl.net.AbstractMCLConnection;
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.Statement;
@@ -202,7 +202,7 @@ public class MonetStatement extends Mone
 			boolean first = true;
 			boolean error = false;
 
-			AbstractMonetDBConnection server = connection.getServer();
+			AbstractMCLConnection server = connection.getServer();
 
 			BatchUpdateException e = new BatchUpdateException("Error(s) occurred while executing the batch, see next SQLExceptions for details", "22000", counts);
 			StringBuilder tmpBatch = new StringBuilder(server.getBlockSize());
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedReader.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLReader.java
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedReader.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLReader.java
@@ -1,4 +1,4 @@
-package nl.cwi.monetdb.mcl.connection;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -7,7 +7,7 @@ import java.io.Reader;
 /**
  * Created by ferreira on 11/24/16.
  */
-public abstract class AbstractBufferedReader extends BufferedReader {
+public abstract class AbstractMCLReader extends BufferedReader {
 
     /** The type of the last line read */
     protected int lineType;
@@ -32,7 +32,7 @@ public abstract class AbstractBufferedRe
     /** a line starting with # indicates INFO */
     public final static int INFO      = '#';
 
-    public AbstractBufferedReader(Reader in) {
+    public AbstractMCLReader(Reader in) {
         super(in);
     }
 
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedWriter.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLWriter.java
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractBufferedWriter.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/AbstractMCLWriter.java
@@ -1,4 +1,4 @@
-package nl.cwi.monetdb.mcl.connection;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.BufferedWriter;
 import java.io.IOException;
@@ -7,11 +7,11 @@ import java.io.Writer;
 /**
  * Created by ferreira on 11/24/16.
  */
-public abstract class AbstractBufferedWriter extends BufferedWriter {
+public abstract class AbstractMCLWriter extends BufferedWriter {
 
-    protected AbstractBufferedReader reader;
+    protected AbstractMCLReader reader;
 
-    public AbstractBufferedWriter(Writer out) {
+    public AbstractMCLWriter(Writer out) {
         super(out);
     }
 
@@ -20,9 +20,9 @@ public abstract class AbstractBufferedWr
      * receives a linetype reset when a line is written from this
      * writer.
      *
-     * @param r an AbstractBufferedReader
+     * @param r an AbstractMCLReader
      */
-    public void registerReader(AbstractBufferedReader r) {
+    public void registerReader(AbstractMCLReader r) {
         this.reader = r;
     }
 
rename from src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLReader.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java
--- a/src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLReader.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLReader.java
@@ -6,9 +6,7 @@
  * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
  */
 
-package nl.cwi.monetdb.mcl.net;
-
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -42,7 +40,7 @@ import java.io.UnsupportedEncodingExcept
  * @see nl.cwi.monetdb.mcl.net.MapiSocket
  * @see BufferedMCLWriter
  */
-public class BufferedMCLReader extends AbstractBufferedReader {
+public class BufferedMCLReader extends AbstractMCLReader {
 
 	/**
 	 * Create a buffering character-input stream that uses a
rename from src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLWriter.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java
--- a/src/main/java/nl/cwi/monetdb/mcl/net/BufferedMCLWriter.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/BufferedMCLWriter.java
@@ -6,9 +6,7 @@
  * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
  */
 
-package nl.cwi.monetdb.mcl.net;
-
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.*;
 
@@ -33,7 +31,7 @@ import java.io.*;
  * @see nl.cwi.monetdb.mcl.net.MapiSocket
  * @see BufferedMCLWriter
  */
-public class BufferedMCLWriter extends AbstractBufferedWriter {
+public class BufferedMCLWriter extends AbstractMCLWriter {
 
 	/**
 	 * Create a buffered character-output stream that uses a
@@ -69,6 +67,7 @@ public class BufferedMCLWriter extends A
 		this.write('\n');
 	}
 
+	@Override
 	public void writeLine(String line) throws IOException {
 		this.write(line);
 		this.flush();
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedReader.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java
--- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedReader.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLReader.java
@@ -1,21 +1,19 @@
-package nl.cwi.monetdb.mcl.embedded;
-
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.*;
 
 /**
  * Created by ferreira on 11/24/16.
  */
-public class EmbeddedReader extends AbstractBufferedReader {
+public class EmbeddedMCLReader extends AbstractMCLReader {
 
-    protected EmbeddedReader() {
+    public EmbeddedMCLReader() {
         super(null);
     }
 
     @Override
     public String readLine() throws IOException {
-        String res = this.readLineInternal();
+        String res = this.readLineInternal(); //this readline will never wait!!
         setLineType(res);
         if (lineType == ERROR && !res.matches("^![0-9A-Z]{5}!.+"))
             res = "!22000!" + res.substring(1);
@@ -25,18 +23,11 @@ public class EmbeddedReader extends Abst
     @Override
     public synchronized String waitForPrompt() throws IOException {
         try {
-            this.wait();
+            this.wait(); //must mimic the socket readline with the wait/notify methods
         } catch (InterruptedException e) {
             throw new IOException(e);
         }
-        String res = this.readLine();
-        if (res == null) {
-            throw new IOException("Connection to server lost!");
-        }
-        if (lineType == ERROR) {
-            return "\n" + res.substring(1);
-        }
-        return res.trim();
+        return null;
     }
 
     private native String readLineInternal();
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedWriter.java
rename to src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java
--- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedWriter.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/io/EmbeddedMCLWriter.java
@@ -1,22 +1,21 @@
-package nl.cwi.monetdb.mcl.embedded;
-
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
+package nl.cwi.monetdb.mcl.io;
 
 import java.io.*;
 
 /**
  * Created by ferreira on 11/24/16.
  */
-public class EmbeddedWriter extends AbstractBufferedWriter {
+public class EmbeddedMCLWriter extends AbstractMCLWriter {
 
-    public EmbeddedWriter() {
+    public EmbeddedMCLWriter(EmbeddedMCLReader reader) {
         super(null);
+        this.reader = reader;
     }
 
     @Override
     public void writeLine(String line) throws IOException {
         this.writeInternal(line);
-        this.reader.notify();
+        this.reader.notify(); //wake up the embedded reader.
     }
 
     private native void writeInternal(String str);
rename from src/main/java/nl/cwi/monetdb/mcl/connection/AbstractMonetDBConnection.java
rename to src/main/java/nl/cwi/monetdb/mcl/net/AbstractMCLConnection.java
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/AbstractMonetDBConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/net/AbstractMCLConnection.java
@@ -1,7 +1,12 @@
-package nl.cwi.monetdb.mcl.connection;
+package nl.cwi.monetdb.mcl.net;
 
 import nl.cwi.monetdb.mcl.MCLException;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
+import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
+import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
+import nl.cwi.monetdb.mcl.parser.TupleLineParser;
 
 import java.io.*;
 import java.net.SocketException;
@@ -10,7 +15,7 @@ import java.util.List;
 /**
  * Created by ferreira on 11/23/16.
  */
-public abstract class AbstractMonetDBConnection {
+public abstract class AbstractMCLConnection {
 
     /** the SQL language */
     public final static int LANG_SQL = 0;
@@ -43,16 +48,16 @@ public abstract class AbstractMonetDBCon
     /** A template to apply to each command (like pre and post fixes) */
     protected String[] commandTempl = new String[3]; // pre, post, sep
 
-    public AbstractMonetDBConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String[] queryTempl, String[] commandTempl) {
+    public AbstractMCLConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String[] queryTempl, String[] commandTempl) {
         this.hostname = hostname;
         this.port = port;
         this.database = database;
         this.username = username;
         this.debug = debug;
         this.hash = hash;
-        this.setLanguage(language);
         this.queryTempl = queryTempl;
         this.commandTempl = commandTempl;
+        this.setLanguage(language);
     }
 
     public String getHostname() {
@@ -110,33 +115,7 @@ public abstract class AbstractMonetDBCon
      *
      * @param language the language
      */
-    public void setLanguage(String language) {
-        this.language = language;
-        if ("sql".equals(language)) {
-            lang = LANG_SQL;
-        } else if ("mal".equals(language)) {
-            lang = LANG_MAL;
-        } else {
-            lang = LANG_UNKNOWN;
-        }
-        if (lang == LANG_SQL) {
-            queryTempl[0] = "s";		// pre
-            queryTempl[1] = "\n;";		// post
-            queryTempl[2] = "\n;\n";	// separator
-
-            commandTempl[0] = "X";		// pre
-            commandTempl[1] = null;		// post
-            commandTempl[2] = "\nX";	// separator
-        } else if (lang == LANG_MAL) {
-            queryTempl[0] = null;
-            queryTempl[1] = ";\n";
-            queryTempl[2] = ";\n";
-
-            commandTempl[0] = null;		// pre
-            commandTempl[1] = null;		// post
-            commandTempl[2] = null;		// separator
-        }
-    }
+    public abstract void setLanguage(String language);
 
     public int getLang() {
         return lang;
@@ -214,7 +193,7 @@ public abstract class AbstractMonetDBCon
      *
      * @return a BufferedMCLReader connected to this MapiSocket
      */
-    public abstract AbstractBufferedReader getReader();
+    public abstract AbstractMCLReader getReader();
 
     /**
      * Returns a Writer for this MapiSocket.  The Writer is a
@@ -223,7 +202,7 @@ public abstract class AbstractMonetDBCon
      *
      * @return a BufferedMCLWriter connected to this MapiSocket
      */
-    public abstract AbstractBufferedWriter getWriter();
+    public abstract AbstractMCLWriter getWriter();
 
     /**
      * Enables logging to a file what is read and written from and to
@@ -307,4 +286,10 @@ public abstract class AbstractMonetDBCon
     public abstract String getJDBCURL();
 
     public abstract int getBlockSize();
+
+    public abstract StartOfHeaderParser getStartOfHeaderParser();
+
+    public abstract HeaderLineParser getHeaderLineParser(int capacity);
+
+    public abstract TupleLineParser getTupleLineParser(int capacity);
 }
rename from src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedConnection.java
rename to src/main/java/nl/cwi/monetdb/mcl/net/EmbeddedMonetDB.java
--- a/src/main/java/nl/cwi/monetdb/mcl/embedded/EmbeddedConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/net/EmbeddedMonetDB.java
@@ -1,13 +1,20 @@
-package nl.cwi.monetdb.mcl.embedded;
+package nl.cwi.monetdb.mcl.net;
 
 import nl.cwi.monetdb.embedded.env.IEmbeddedConnection;
 import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedDatabase;
 import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedException;
 import nl.cwi.monetdb.mcl.MCLException;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
-import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
+import nl.cwi.monetdb.mcl.io.EmbeddedMCLReader;
+import nl.cwi.monetdb.mcl.io.EmbeddedMCLWriter;
+import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
+import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
+import nl.cwi.monetdb.mcl.parser.TupleLineParser;
+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.*;
 import java.net.SocketException;
@@ -16,7 +23,7 @@ import java.util.List;
 /**
  * Created by ferreira on 11/23/16.
  */
-public class EmbeddedConnection extends AbstractMonetDBConnection implements IEmbeddedConnection {
+public class EmbeddedMonetDB extends AbstractMCLConnection implements IEmbeddedConnection {
 
     private long connectionPointer;
 
@@ -24,12 +31,12 @@ public class EmbeddedConnection extends 
 
     private final String directory;
 
-    private EmbeddedReader reader;
+    private EmbeddedMCLReader reader;
 
-    private EmbeddedWriter writer;
+    private EmbeddedMCLWriter writer;
 
-    public EmbeddedConnection(String hostname, int port, String database, String username, boolean debug, String language, String hash, String directory) {
-        super(hostname, port, database, username, debug, language, hash, new String[]{"s", "\n;", "\n;\n"}, new String[]{"X", null, "\nX"});
+    public EmbeddedMonetDB(String hostname, int port, String database, String username, boolean debug, String language, String hash, String directory) {
+        super(hostname, port, database, username, debug, language, hash, new String[]{"", "\n;", "\n;\n"}, new String[]{"X", null, "\nX"});
         this.directory = directory;
     }
 
@@ -57,7 +64,6 @@ public class EmbeddedConnection extends 
         if(this.lang != LANG_SQL) {
             throw new IllegalArgumentException("The embedded connection only supports the SQL language!");
         }
-        super.setLanguage(language);
     }
 
     @Override
@@ -83,8 +89,8 @@ public class EmbeddedConnection extends 
             } else {
                 MonetDBEmbeddedDatabase.StartDatabase(this.directory, true, false);
             }
-            this.reader = new EmbeddedReader();
-            this.writer = new EmbeddedWriter();
+            this.reader = new EmbeddedMCLReader();
+            this.writer = new EmbeddedMCLWriter(this.reader);
             MonetDBEmbeddedDatabase.AddJDBCEmbeddedConnection(this);
         } catch (MonetDBEmbeddedException ex) {
             throw new MCLException(ex);
@@ -103,12 +109,12 @@ public class EmbeddedConnection extends 
     }
 
     @Override
-    public AbstractBufferedReader getReader() {
+    public AbstractMCLReader getReader() {
         return this.reader;
     }
 
     @Override
-    public AbstractBufferedWriter getWriter() {
+    public AbstractMCLWriter getWriter() {
         return this.writer;
     }
 
@@ -133,6 +139,21 @@ public class EmbeddedConnection extends 
     }
 
     @Override
+    public StartOfHeaderParser getStartOfHeaderParser() {
+        return new EmbeddedStartOfHeaderParser();
+    }
+
+    @Override
+    public HeaderLineParser getHeaderLineParser(int capacity) {
+        return new EmbeddedHeaderLineParser(capacity);
+    }
+
+    @Override
+    public TupleLineParser getTupleLineParser(int capacity) {
+        return new EmbeddedTupleLineParser(capacity);
+    }
+
+    @Override
     public long getConnectionPointer() {
         return connectionPointer;
     }
--- a/src/main/java/nl/cwi/monetdb/mcl/net/MapiSocket.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/net/MapiSocket.java
@@ -29,10 +29,17 @@ import java.util.List;
 import java.util.Set;
 
 import nl.cwi.monetdb.mcl.MCLException;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
-import nl.cwi.monetdb.mcl.connection.AbstractMonetDBConnection;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
+import nl.cwi.monetdb.mcl.io.BufferedMCLReader;
+import nl.cwi.monetdb.mcl.io.BufferedMCLWriter;
+import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
+import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
+import nl.cwi.monetdb.mcl.parser.TupleLineParser;
+import nl.cwi.monetdb.mcl.parser.socket.SocketHeaderLineParser;
+import nl.cwi.monetdb.mcl.parser.socket.SocketStartOfHeaderParser;
+import nl.cwi.monetdb.mcl.parser.socket.SocketTupleLineParser;
 
 /**
  * A Socket for communicating with the MonetDB database in MAPI block
@@ -84,7 +91,7 @@ import nl.cwi.monetdb.mcl.parser.MCLPars
  * @see BufferedMCLReader
  * @see BufferedMCLWriter
  */
-public final class MapiSocket extends AbstractMonetDBConnection {
+public final class MapiSocket extends AbstractMCLConnection {
 
 	/** The blocksize (hardcoded in compliance with stream.mx) */
 	private static final int BLOCK = 8 * 1024 - 2;
@@ -130,7 +137,7 @@ public final class MapiSocket extends Ab
 	private byte[] blklen = new byte[2];
 
 	public MapiSocket(String hostname, int port, String database, String username, boolean debug, String language, String hash) {
-		super(hostname, port, database, username, debug, language, hash, new String[]{"s", "\n;", "\n;\n"}, new String[]{"s", "\n;", "\n;\n"});
+		super(hostname, port, database, username, debug, language, hash, new String[]{"", "\n;", "\n;\n"}, new String[]{"", "\n;", "\n;\n"});
 	}
 
 	@Override
@@ -165,6 +172,39 @@ public final class MapiSocket extends Ab
 	}
 
 	/**
+	 * Sets the language to use for this connection.
+	 *
+	 * @param language the language
+	 */
+	public void setLanguage(String language) {
+		this.language = language;
+		if ("sql".equals(language)) {
+			lang = LANG_SQL;
+		} else if ("mal".equals(language)) {
+			lang = LANG_MAL;
+		} else {
+			lang = LANG_UNKNOWN;
+		}
+		if (lang == LANG_SQL) {
+			queryTempl[0] = "s";		// pre
+			queryTempl[1] = "\n;";		// post
+			queryTempl[2] = "\n;\n";	// separator
+
+			commandTempl[0] = "X";		// pre
+			commandTempl[1] = null;		// post
+			commandTempl[2] = "\nX";	// separator
+		} else if (lang == LANG_MAL) {
+			queryTempl[0] = null;
+			queryTempl[1] = ";\n";
+			queryTempl[2] = ";\n";
+
+			commandTempl[0] = null;		// pre
+			commandTempl[1] = null;		// post
+			commandTempl[2] = null;		// separator
+		}
+	}
+
+	/**
 	 * Sets whether MCL redirections should be followed or not.  If set
 	 * to false, an MCLException will be thrown when a redirect is
 	 * encountered during connect.  The default bahaviour is to
@@ -527,12 +567,12 @@ public final class MapiSocket extends Ab
 	}
 
 	@Override
-	public AbstractBufferedReader getReader() {
+	public AbstractMCLReader getReader() {
 		return reader;
 	}
 
 	@Override
-	public AbstractBufferedWriter getWriter() {
+	public AbstractMCLWriter getWriter() {
 		return writer;
 	}
 
@@ -966,7 +1006,7 @@ public final class MapiSocket extends Ab
 	@Override
 	public String getJDBCURL() {
 		String language = "";
-		if (this.getLang() == AbstractMonetDBConnection.LANG_MAL)
+		if (this.getLang() == AbstractMCLConnection.LANG_MAL)
 			language = "?language=mal";
 		return "jdbc:monetdb://" + this.getHostname() + ":" + this.getPort() + "/" + this.getDatabase() + language;
 	}
@@ -975,4 +1015,19 @@ public final class MapiSocket extends Ab
 	public int getBlockSize() {
 		return BLOCK;
 	}
+
+	@Override
+	public StartOfHeaderParser getStartOfHeaderParser() {
+		return new SocketStartOfHeaderParser();
+	}
+
+	@Override
+	public HeaderLineParser getHeaderLineParser(int capacity) {
+		return new SocketHeaderLineParser(capacity);
+	}
+
+	@Override
+	public TupleLineParser getTupleLineParser(int capacity) {
+		return new SocketTupleLineParser(capacity);
+	}
 }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java
@@ -1,181 +1,25 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0.  If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
- */
-
 package nl.cwi.monetdb.mcl.parser;
 
-
 /**
- * The HeaderLineParser is a generic MCLParser that extracts values from
- * a metadata header in the MCL protocol either as string or integer
- * values.
- *
- * @author Fabian Groffen <Fabian.Groffen>
+ * Created by ferreira on 11/25/16.
  */
-public class HeaderLineParser extends MCLParser {
-	private int type;
-
-	public final static int NAME       = 1;
-	public final static int LENGTH     = 2;
-	public final static int TABLE      = 3;
-	public final static int TYPE       = 4;
-
-	/**
-	 * Constructs a HeaderLineParser which expects columncount columns.
-	 *
-	 * @param columncount the number of columns in the to be parsed string
-	 */
-	public HeaderLineParser(int columncount) {
-		super(columncount);
-	}
+public abstract class HeaderLineParser extends MCLParser {
 
-	/**
-	 * Parses the given String source as header line.  If source cannot
-	 * be parsed, an MCLParseException is thrown.  The columncount argument
-	 * given during construction is used for allocation of the backing
-	 * array.  Parsing a header line with has more fields will therefore
-	 * result in a crash.  While this seems illogical, the caller should
-	 * know this size, since the StartOfHeader contains this
-	 * information.
-	 *
-	 * @param source a String which should be parsed
-	 * @return the type of then parsed header line
-	 * @throws MCLParseException if an error occurs during parsing
-	 */
-	@Override
-	public int parse(String source) throws MCLParseException {
-		char[] chrLine = source.toCharArray();
-		int len = chrLine.length;
-		int pos = 0;
-		boolean foundChar = false;
-		boolean nameFound = false;
-		// find header name
-		for (int i = len - 1; i >= 0; i--) {
-			switch (chrLine[i]) {
-				case ' ':
-				case '\n':
-				case '\t':
-				case '\r':
-					if (!foundChar) {
-						len = i - 1;
-					} else {
-						pos = i + 1;
-					}
-					break;
-				case '#':
-					// found!
-					nameFound = true;
-					if (pos == 0) pos = i + 1;
-					i = 0;	// force the loop to terminate
-					break;
-				default:
-					foundChar = true;
-					pos = 0;
-					break;
-			}
-		}
-		if (!nameFound)
-			throw new MCLParseException("invalid header, no header name found", pos);
+    public final static int NAME       = 1;
+    public final static int LENGTH     = 2;
+    public final static int TABLE      = 3;
+    public final static int TYPE       = 4;
+
+    protected int type;
 
-		// depending on the name of the header, we continue
-		switch (chrLine[pos]) {
-			case 'n':
-				if (len - pos == 4 &&
-						source.regionMatches(pos + 1, "name", 1, 3))
-				{
-					getValues(chrLine, 2, pos - 3);
-					type = NAME;
-				}
-				break;
-			case 'l':
-				if (len - pos == 6 &&
-						source.regionMatches(pos + 1, "length", 1, 5))
-				{
-					getIntValues(chrLine, 2, pos - 3);
-					type = LENGTH;
-				}
-				break;
-			case 't':
-				if (len - pos == 4 &&
-						source.regionMatches(pos + 1, "type", 1, 3))
-				{
-					getValues(chrLine, 2, pos - 3);
-					type = TYPE;
-				} else if (len - pos == 10 &&
-						source.regionMatches(pos + 1, "table_name", 1, 9))
-				{
-					getValues(chrLine, 2, pos - 3);
-					type = TABLE;
-				}
-				break;
-			default:
-				throw new MCLParseException("unknown header: " +
-						(new String(chrLine, pos, len - pos)));
-		}
-
-		// adjust colno
-		reset();
-
-		return type;
-	}
-
-	/**
-	 * Returns an array of Strings containing the values between
-	 * ',\t' separators.  Note that no quoting/dequoting is done in this
-	 * method.
-	 *
-	 * @param chrLine a character array holding the input data
-	 * @param start where the relevant data starts
-	 * @param stop where the relevant data stops
-	 */
-	final private void getValues(char[] chrLine, int start, int stop) {
-		int elem = 0;
-
-		for (int i = start + 1; i < stop; i++) {
-			if (chrLine[i] == '\t' && chrLine[i - 1] == ',') {
-				values[elem++] =
-					new String(chrLine, start, i - 1 - start);
-				start = i + 1;
-			}
-		}
-		// add the left over part
-		values[elem + 1] = new String(chrLine, start, stop - start);
-	}
-
-	/**
-	 * Returns an array of ints containing the values between
-	 * ',\t' separators.
-	 *
-	 * @param chrLine a character array holding the input data
-	 * @param start where the relevant data starts
-	 * @param stop where the relevant data stops
-	 */
-	final private void getIntValues(char[] chrLine, int start, int stop)
-		throws MCLParseException
-	{
-		int elem = 0;
-		int tmp = 0;
-
-		for (int i = start; i < stop; i++) {
-			if (chrLine[i] == ',' && chrLine[i + 1] == '\t') {
-				intValues[elem++] = tmp;
-				tmp = 0;
-			} else {
-				tmp *= 10;
-				// note: don't use Character.isDigit() here, because
-				// we only want ISO-LATIN-1 digits
-				if (chrLine[i] >= '0' && chrLine[i] <= '9') {
-					tmp += (int)chrLine[i] - (int)'0';
-				} else {
-					throw new MCLParseException("expected a digit in " + new String(chrLine) + " at " + i);
-				}
-			}
-		}
-		// add the left over part
-		intValues[elem + 1] = tmp;
-	}
+    /**
+     * 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
+     */
+    protected HeaderLineParser(int capacity) {
+        super(capacity);
+    }
 }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/MCLParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/MCLParser.java
@@ -8,7 +8,6 @@
 
 package nl.cwi.monetdb.mcl.parser;
 
-
 /**
  * Interface for parsers in MCL.  The parser family in MCL is set up as
  * a reusable object.  This allows the same parser to be used again for
@@ -54,13 +53,13 @@ public abstract class MCLParser {
 	 * @see #nextInt()
 	 * @see #hasNext()
 	 */
-	abstract public int parse(String source) throws MCLParseException;
+	public abstract int parse(String source) throws MCLParseException;
 
 	/**
 	 * Repositions the internal field offset to the start, such that the
 	 * next call to next() will return the first field again.
 	 */
-	final public void reset() {
+	public final void reset() {
 		colnr = 0;
 	}
 
@@ -72,7 +71,7 @@ public abstract class MCLParser {
 	 * @see #next()
 	 * @see #nextInt()
 	 */
-	final public boolean hasNext() {
+	public final boolean hasNext() {
 		return colnr < values.length;
 	}
 
@@ -86,7 +85,7 @@ public abstract class MCLParser {
 	 * @see #nextInt()
 	 * @see #hasNext()
 	 */
-	final public String next() {
+	public final String next() {
 		return values[colnr++];
 	}
 
@@ -99,7 +98,7 @@ public abstract class MCLParser {
 	 * @return the current field value as integer
 	 * @see #next()
 	 */
-	final public int nextInt() {
+	public final int nextInt() {
 		return intValues[colnr++];
 	}
 }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java
@@ -1,138 +1,45 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0.  If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
- */
-
 package nl.cwi.monetdb.mcl.parser;
 
-import java.nio.CharBuffer;
-
 /**
- * The StartOfHeaderParser allows easy examination of a start of header
- * line.  It does not fit into the general MCLParser framework because
- * it uses a different interface.  While the parser is very shallow, it
- * requires the caller to know about the header lines that are parsed.
- * All this parser does is detect the (valid) type of a soheader, and
- * allow to return the fields in it as integer or string.  An extra
- * bonus is that it can return if another field should be present in the
- * soheader.
- *
- * @author Fabian Groffen <Fabian.Groffen>
+ * Created by ferreira on 11/25/16.
  */
-public class StartOfHeaderParser {
-	private CharBuffer soh = null;
-	private int len;
-	private int pos;
-
-	/* Query types (copied from sql_query.mx) */
+public abstract class StartOfHeaderParser {
 
-	/** A parse response (not handled) */
-	public final static int Q_PARSE    = '0';
-	/** A tabular response (typical ResultSet) */
-	public final static int Q_TABLE    = '1';
-	/** A response to an update statement, contains number of affected
-	 * rows and generated key-id */
-	public final static int Q_UPDATE   = '2';
-	/** A response to a schema update */
-	public final static int Q_SCHEMA   = '3';
-	/** A response to a transation statement (start, rollback, abort,
-	 * commit) */
-	public final static int Q_TRANS    = '4';
-	/** A tabular response in response to a PREPARE statement containing
-	 * information about the wildcard values that need to be supplied */
-	public final static int Q_PREPARE  = '5';
-	/** A tabular continuation response (for a ResultSet) */
-	public final static int Q_BLOCK    = '6';
-	/** An unknown and unsupported response */
-	public final static int Q_UNKNOWN  =  0 ;
+    /* Query types (copied from sql_query.mx) */
 
-	public final int parse(String in) throws MCLParseException {
-		soh = CharBuffer.wrap(in);
-		soh.get();	// skip the &
-		int type = soh.get();
-		switch (type) {
-			default:
-				throw new MCLParseException("invalid or unknown header", 1);
-			case Q_PARSE:
-			case Q_SCHEMA:
-				len = 0;
-			break;
-			case Q_TABLE:
-			case Q_PREPARE:
-				len = 4;
-				soh.get();
-			break;
-			case Q_UPDATE:
-				len = 2;
-				soh.get();
-			break;
-			case Q_TRANS:
-				len = 1;
-				soh.get();
-			break;
-			case Q_BLOCK:
-				len = 3;
-				soh.get();
-			break;
-		}
-		pos = 0;
-		return type;
-	}
-
-	public final boolean hasNext() {
-		return pos < len;
-	}
+    /** A parse response (not handled) */
+    public final static int Q_PARSE    = '0';
+    /** A tabular response (typical ResultSet) */
+    public final static int Q_TABLE    = '1';
+    /** A response to an update statement, contains number of affected
+     * rows and generated key-id */
+    public final static int Q_UPDATE   = '2';
+    /** A response to a schema update */
+    public final static int Q_SCHEMA   = '3';
+    /** A response to a transaction statement (start, rollback, abort,
+     * commit) */
+    public final static int Q_TRANS    = '4';
+    /** A tabular response in response to a PREPARE statement containing
+     * information about the wildcard values that need to be supplied */
+    public final static int Q_PREPARE  = '5';
+    /** A tabular continuation response (for a ResultSet) */
+    public final static int Q_BLOCK    = '6';
+    /** An unknown and unsupported response */
+    public final static int Q_UNKNOWN  =  0;
 
-	/**
-	 * Returns the next token in the CharBuffer as integer. The value is
-	 * considered to end at the end of the CharBuffer or at a space.  If
-	 * a non-numeric character is encountered an MCLParseException is
-	 * thrown.
-	 *
-	 * @return The next token in the CharBuffer as integer
-	 * @throws MCLParseException if no numeric value could be read
-	 */
-	public final int getNextAsInt() throws MCLParseException {
-		pos++;
-		if (!soh.hasRemaining()) throw
-			new MCLParseException("unexpected end of string", soh.position() - 1);
-		int tmp;
-		char chr = soh.get();
-		// note: don't use Character.isDigit() here, because
-		// we only want ISO-LATIN-1 digits
-		if (chr >= '0' && chr <= '9') {
-			tmp = (int)chr - (int)'0';
-		} else {
-			throw new MCLParseException("expected a digit", soh.position() - 1);
-		}
+    protected int len;
+
+    protected int pos;
+
+    public StartOfHeaderParser() {}
+
+    public abstract int parse(String in) throws MCLParseException;
 
-		while (soh.hasRemaining() && (chr = soh.get()) != ' ') {
-			tmp *= 10;
-			if (chr >= '0' && chr <= '9') {
-				tmp += (int)chr - (int)'0';
-			} else {
-				throw new MCLParseException("expected a digit", soh.position() - 1);
-			}
-		}
+    public abstract int getNextAsInt() throws MCLParseException;
 
-		return tmp;
-	}
+    public abstract String getNextAsString() throws MCLParseException;
 
-	public final String getNextAsString() throws MCLParseException {
-		pos++;
-		if (!soh.hasRemaining()) throw
-			new MCLParseException("unexpected end of string", soh.position() - 1);
-		int cnt = 0;
-		soh.mark();
-		while (soh.hasRemaining() && soh.get() != ' ') {
-			cnt++;
-		}
-
-		soh.reset();
-
-		return soh.subSequence(0, cnt).toString();
-	}
+    public final boolean hasNext() {
+        return pos < len;
+    }
 }
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java
@@ -1,183 +1,17 @@
-/*
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0.  If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
- */
-
 package nl.cwi.monetdb.mcl.parser;
 
 /**
- * The TupleLineParser extracts the values from a given tuple.  The
- * number of values that are expected are known upfront to speed up
- * allocation and validation.
- *
- * @author Fabian Groffen <Fabian.Groffen>
+ * Created by ferreira on 11/25/16.
  */
-public class TupleLineParser extends MCLParser {
-	/**
-	 * Constructs a TupleLineParser which expects columncount columns.
-	 *
-	 * @param columncount the number of columns in the to be parsed string
-	 */
-	public TupleLineParser(int columncount) {
-		super(columncount);
-	}
-
-	/**
-	 * Parses the given String source as tuple line.  If source cannot
-	 * be parsed, a ParseException is thrown.  The columncount argument
-	 * is used for allocation of the returned array.  While this seems
-	 * illogical, the caller should know this size, since the
-	 * StartOfHeader contains this information.
-	 *
-	 * @param source a String which should be parsed
-	 * @return 0, as there is no 'type' of TupleLine
-	 * @throws MCLParseException if an error occurs during parsing
-	 */
-	@Override
-	public int parse(String source) throws MCLParseException {
-		int len = source.length();
-		char[] chrLine = new char[len];
-		source.getChars(0, len, chrLine, 0);
-
-		// first detect whether this is a single value line (=) or a
-		// real tuple ([)
-		if (chrLine[0] == '=') {
-			if (values.length != 1)
-				throw new MCLParseException(values.length +
-						" columns expected, but only single value found");
-
-			// return the whole string but the leading =
-			values[0] = source.substring(1);
-
-			// reset colnr
-			reset();
-
-			return 0;
-		}
-
-		// extract separate fields by examining string, char for char
-		boolean inString = false, escaped = false;
-		int cursor = 2, column = 0, i = 2;
-		StringBuilder uesc = new StringBuilder();
-		for (; i < len; i++) {
-			switch(chrLine[i]) {
-				default:
-					escaped = false;
-				break;
-				case '\\':
-					escaped = !escaped;
-				break;
-				case '"':
-					/**
-					 * If all strings are wrapped between two quotes, a \" can
-					 * never exist outside a string. Thus if we believe that we
-					 * are not within a string, we can safely assume we're about
-					 * to enter a string if we find a quote.
-					 * If we are in a string we should stop being in a string if
-					 * we find a quote which is not prefixed by a \, for that
-					 * would be an escaped quote. However, a nasty situation can
-					 * occur where the string is like "test \\" as obvious, a
-					 * test for a \ in front of a " doesn't hold here for all
-					 * cases. Because "test \\\"" can exist as well, we need to
-					 * know if a quote is prefixed by an escaping slash or not.
-					 */
-					if (!inString) {
-						inString = true;
-					} else if (!escaped) {
-						inString = false;
-					}
-
-					// reset escaped flag
-					escaped = false;
-				break;
-				case '\t':
-					if (!inString &&
-						(i > 0 && chrLine[i - 1] == ',') ||
-						(i + 1 == len - 1 && chrLine[++i] == ']')) // dirty
-					{
-						// split!
-						if (chrLine[cursor] == '"' &&
-							chrLine[i - 2] == '"')
-						{
-							// reuse the StringBuilder by cleaning it
-							uesc.delete(0, uesc.length());
-							// prevent capacity increasements
-							uesc.ensureCapacity((i - 2) - (cursor + 1));
-							for (int pos = cursor + 1; pos < i - 2; pos++) {
-								if (chrLine[pos] == '\\' && pos + 1 < i - 2) {
-									pos++;
-									// strToStr and strFromStr in gdk_atoms.mx only
-									// support \t \n \\ \" and \377
-									switch (chrLine[pos]) {
-										case '\\':
-											uesc.append('\\');
-										break;
-										case 'n':
-											uesc.append('\n');
-										break;
-										case 't':
-											uesc.append('\t');
-										break;
-										case '"':
-											uesc.append('"');
-										break;
-										case '0': case '1': case '2': case '3':
-											// this could be an octal number, let's check it out
-											if (pos + 2 < i - 2 &&
-												chrLine[pos + 1] >= '0' && chrLine[pos + 1] <= '7' &&
-												chrLine[pos + 2] >= '0' && chrLine[pos + 2] <= '7'
-											) {
-												// we got the number!
-												try {
-													uesc.append((char)(Integer.parseInt("" + chrLine[pos] + chrLine[pos + 1] + chrLine[pos + 2], 8)));
-													pos += 2;
-												} catch (NumberFormatException e) {
-													// hmmm, this point should never be reached actually...
-													throw new AssertionError("Flow error, should never try to parse non-number");
-												}
-											} else {
-												// do default action if number seems not to be correct
-												uesc.append(chrLine[pos]);
-											}
-										break;
-										default:
-											// this is wrong, just ignore the escape, and print the char
-											uesc.append(chrLine[pos]);
-										break;
-									}
-								} else {
-									uesc.append(chrLine[pos]);
-								}
-							}
-
-							// put the unescaped string in the right place
-							values[column++] = uesc.toString();
-						} else if ((i - 1) - cursor == 4 &&
-								source.indexOf("NULL", cursor) == cursor)
-						{
-							values[column++] = null;
-						} else {
-							values[column++] =
-								source.substring(cursor, i - 1);
-						}
-						cursor = i + 1;
-					}
-
-					// reset escaped flag
-					escaped = false;
-				break;
-			}
-		}
-		// check if this result is of the size we expected it to be
-		if (column != values.length)
-			throw new MCLParseException("illegal result length: " + column + "\nlast read: " + (column > 0 ? values[column - 1] : "<none>"));
-
-		// reset colnr
-		reset();
-		
-		return 0;
-	}
+public abstract class TupleLineParser extends MCLParser {
+    /**
+     * 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
+     */
+    protected TupleLineParser(int capacity) {
+        super(capacity);
+    }
 }
new file mode 100644
--- /dev/null
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedHeaderLineParser.java
@@ -0,0 +1,26 @@
+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 {
+
+    /**
+     * 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 {
+        return 0;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedStartOfHeaderParser.java
@@ -0,0 +1,25 @@
+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 {
+
+    @Override
+    public int parse(String in) throws MCLParseException {
+        return 0;
+    }
+
+    @Override
+    public int getNextAsInt() throws MCLParseException {
+        return 0;
+    }
+
+    @Override
+    public String getNextAsString() throws MCLParseException {
+        return null;
+    }
+}
new file mode 100644
--- /dev/null
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/embedded/EmbeddedTupleLineParser.java
@@ -0,0 +1,26 @@
+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;
+    }
+}
copy from src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java
copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketHeaderLineParser.java
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/HeaderLineParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketHeaderLineParser.java
@@ -6,30 +6,28 @@
  * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
  */
 
-package nl.cwi.monetdb.mcl.parser;
+package nl.cwi.monetdb.mcl.parser.socket;
 
 
+import nl.cwi.monetdb.mcl.parser.HeaderLineParser;
+import nl.cwi.monetdb.mcl.parser.MCLParseException;
+import nl.cwi.monetdb.mcl.parser.MCLParser;
+
 /**
- * The HeaderLineParser is a generic MCLParser that extracts values from
+ * The SocketHeaderLineParser is a generic MCLParser that extracts values from
  * a metadata header in the MCL protocol either as string or integer
  * values.
  *
  * @author Fabian Groffen <Fabian.Groffen>
  */
-public class HeaderLineParser extends MCLParser {
-	private int type;
-
-	public final static int NAME       = 1;
-	public final static int LENGTH     = 2;
-	public final static int TABLE      = 3;
-	public final static int TYPE       = 4;
+public class SocketHeaderLineParser extends HeaderLineParser {
 
 	/**
-	 * Constructs a HeaderLineParser which expects columncount columns.
+	 * Constructs a SocketHeaderLineParser which expects columncount columns.
 	 *
 	 * @param columncount the number of columns in the to be parsed string
 	 */
-	public HeaderLineParser(int columncount) {
+	public SocketHeaderLineParser(int columncount) {
 		super(columncount);
 	}
 
@@ -88,7 +86,7 @@ public class HeaderLineParser extends MC
 						source.regionMatches(pos + 1, "name", 1, 3))
 				{
 					getValues(chrLine, 2, pos - 3);
-					type = NAME;
+					type = HeaderLineParser.NAME;
 				}
 				break;
 			case 'l':
@@ -96,7 +94,7 @@ public class HeaderLineParser extends MC
 						source.regionMatches(pos + 1, "length", 1, 5))
 				{
 					getIntValues(chrLine, 2, pos - 3);
-					type = LENGTH;
+					type = HeaderLineParser.LENGTH;
 				}
 				break;
 			case 't':
@@ -104,12 +102,12 @@ public class HeaderLineParser extends MC
 						source.regionMatches(pos + 1, "type", 1, 3))
 				{
 					getValues(chrLine, 2, pos - 3);
-					type = TYPE;
+					type = HeaderLineParser.TYPE;
 				} else if (len - pos == 10 &&
 						source.regionMatches(pos + 1, "table_name", 1, 9))
 				{
 					getValues(chrLine, 2, pos - 3);
-					type = TABLE;
+					type = HeaderLineParser.TABLE;
 				}
 				break;
 			default:
copy from src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java
copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketStartOfHeaderParser.java
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/StartOfHeaderParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketStartOfHeaderParser.java
@@ -6,12 +6,15 @@
  * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
  */
 
-package nl.cwi.monetdb.mcl.parser;
+package nl.cwi.monetdb.mcl.parser.socket;
+
+import nl.cwi.monetdb.mcl.parser.StartOfHeaderParser;
+import nl.cwi.monetdb.mcl.parser.MCLParseException;
 
 import java.nio.CharBuffer;
 
 /**
- * The StartOfHeaderParser allows easy examination of a start of header
+ * The SocketStartOfHeaderParser allows easy examination of a start of header
  * line.  It does not fit into the general MCLParser framework because
  * it uses a different interface.  While the parser is very shallow, it
  * requires the caller to know about the header lines that are parsed.
@@ -22,33 +25,11 @@ import java.nio.CharBuffer;
  *
  * @author Fabian Groffen <Fabian.Groffen>
  */
-public class StartOfHeaderParser {
-	private CharBuffer soh = null;
-	private int len;
-	private int pos;
-
-	/* Query types (copied from sql_query.mx) */
+public class SocketStartOfHeaderParser extends StartOfHeaderParser {
 
-	/** A parse response (not handled) */
-	public final static int Q_PARSE    = '0';
-	/** A tabular response (typical ResultSet) */
-	public final static int Q_TABLE    = '1';
-	/** A response to an update statement, contains number of affected
-	 * rows and generated key-id */
-	public final static int Q_UPDATE   = '2';
-	/** A response to a schema update */
-	public final static int Q_SCHEMA   = '3';
-	/** A response to a transation statement (start, rollback, abort,
-	 * commit) */
-	public final static int Q_TRANS    = '4';
-	/** A tabular response in response to a PREPARE statement containing
-	 * information about the wildcard values that need to be supplied */
-	public final static int Q_PREPARE  = '5';
-	/** A tabular continuation response (for a ResultSet) */
-	public final static int Q_BLOCK    = '6';
-	/** An unknown and unsupported response */
-	public final static int Q_UNKNOWN  =  0 ;
+	private CharBuffer soh = null;
 
+	@Override
 	public final int parse(String in) throws MCLParseException {
 		soh = CharBuffer.wrap(in);
 		soh.get();	// skip the &
@@ -82,10 +63,6 @@ public class StartOfHeaderParser {
 		return type;
 	}
 
-	public final boolean hasNext() {
-		return pos < len;
-	}
-
 	/**
 	 * Returns the next token in the CharBuffer as integer. The value is
 	 * considered to end at the end of the CharBuffer or at a space.  If
@@ -95,6 +72,7 @@ public class StartOfHeaderParser {
 	 * @return The next token in the CharBuffer as integer
 	 * @throws MCLParseException if no numeric value could be read
 	 */
+	@Override
 	public final int getNextAsInt() throws MCLParseException {
 		pos++;
 		if (!soh.hasRemaining()) throw
@@ -121,6 +99,7 @@ public class StartOfHeaderParser {
 		return tmp;
 	}
 
+	@Override
 	public final String getNextAsString() throws MCLParseException {
 		pos++;
 		if (!soh.hasRemaining()) throw
copy from src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java
copy to src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketTupleLineParser.java
--- a/src/main/java/nl/cwi/monetdb/mcl/parser/TupleLineParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/parser/socket/SocketTupleLineParser.java
@@ -6,22 +6,26 @@
  * Copyright 1997 - July 2008 CWI, August 2008 - 2016 MonetDB B.V.
  */
 
-package nl.cwi.monetdb.mcl.parser;
+package nl.cwi.monetdb.mcl.parser.socket;
+
+import nl.cwi.monetdb.mcl.parser.MCLParseException;
+import nl.cwi.monetdb.mcl.parser.TupleLineParser;
 
 /**
- * The TupleLineParser extracts the values from a given tuple.  The
+ * The SocketTupleLineParser extracts the values from a given tuple.  The
  * number of values that are expected are known upfront to speed up
  * allocation and validation.
  *
  * @author Fabian Groffen <Fabian.Groffen>
  */
-public class TupleLineParser extends MCLParser {
+public class SocketTupleLineParser extends TupleLineParser {
+
 	/**
-	 * Constructs a TupleLineParser which expects columncount columns.
+	 * Constructs a SocketTupleLineParser which expects columncount columns.
 	 *
 	 * @param columncount the number of columns in the to be parsed string
 	 */
-	public TupleLineParser(int columncount) {
+	public SocketTupleLineParser(int columncount) {
 		super(columncount);
 	}
 
--- a/src/main/java/nl/cwi/monetdb/merovingian/Control.java
+++ b/src/main/java/nl/cwi/monetdb/merovingian/Control.java
@@ -8,8 +8,8 @@
 
 package nl.cwi.monetdb.merovingian;
 
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
 import nl.cwi.monetdb.mcl.net.MapiSocket;
 import nl.cwi.monetdb.mcl.MCLException;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
@@ -115,8 +115,8 @@ public class Control {
 			String database, String command, boolean hasOutput)
 		throws MerovingianException, IOException
 	{
-		AbstractBufferedReader min;
-		AbstractBufferedWriter mout;
+		AbstractMCLReader min;
+		AbstractMCLWriter mout;
 		MapiSocket ms = new MapiSocket(host, port, "monetdb", "monetdb", false, "sql", "SHA256");
 		ms.setDatabase("merovingian");
 		ms.setLanguage("control");
@@ -205,16 +205,16 @@ public class Control {
 		ArrayList<String> l = new ArrayList<>();
 		String tmpLine = min.readLine();
 		int linetype = min.getLineType();
-		if (linetype == AbstractBufferedReader.ERROR)
+		if (linetype == AbstractMCLReader.ERROR)
 			throw new MerovingianException(tmpLine.substring(6));
-		if (linetype != AbstractBufferedReader.RESULT)
+		if (linetype != AbstractMCLReader.RESULT)
 			throw new MerovingianException("unexpected line: " + tmpLine);
 		if (!tmpLine.substring(1).equals(RESPONSE_OK))
 			throw new MerovingianException(tmpLine.substring(1));
 		tmpLine = min.readLine();
 		linetype = min.getLineType();
-		while (linetype != AbstractBufferedReader.PROMPT) {
-			if (linetype != AbstractBufferedReader.RESULT)
+		while (linetype != AbstractMCLReader.PROMPT) {
+			if (linetype != AbstractMCLReader.RESULT)
 				throw new MerovingianException("unexpected line: " +
 						tmpLine);
 
--- a/src/main/java/nl/cwi/monetdb/util/SQLRestore.java
+++ b/src/main/java/nl/cwi/monetdb/util/SQLRestore.java
@@ -15,8 +15,8 @@ import java.io.IOException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import nl.cwi.monetdb.mcl.MCLException;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedReader;
-import nl.cwi.monetdb.mcl.connection.AbstractBufferedWriter;
+import nl.cwi.monetdb.mcl.io.AbstractMCLReader;
+import nl.cwi.monetdb.mcl.io.AbstractMCLWriter;
 import nl.cwi.monetdb.mcl.net.MapiSocket;
 import nl.cwi.monetdb.mcl.parser.MCLParseException;
 
@@ -42,11 +42,11 @@ public class SQLRestore {
 	}
 	
 	private static class ServerResponseReader implements Runnable {
-		private final AbstractBufferedReader _is;
+		private final AbstractMCLReader _is;
 		private final AtomicBoolean _errorState = new AtomicBoolean(false);
 		private String _errorMessage = null; 
 		
-		ServerResponseReader(AbstractBufferedReader is) {
+		ServerResponseReader(AbstractMCLReader is) {
 			_is = is;
 		}
 		
@@ -58,7 +58,7 @@ public class SQLRestore {
 						break;
 					int result = _is.getLineType();
 					switch (result) { 
-					case AbstractBufferedReader.ERROR:
+					case AbstractMCLReader.ERROR:
 						_errorMessage = line;
 						_errorState.set(true);
 						return;
@@ -108,8 +108,8 @@ public class SQLRestore {
 		try {
 			ms.connect(_user, _password);
 			
-			AbstractBufferedWriter os = ms.getWriter();
-			AbstractBufferedReader reader = ms.getReader();
+			AbstractMCLWriter os = ms.getWriter();
+			AbstractMCLReader reader = ms.getReader();
 			
 			ServerResponseReader srr = new ServerResponseReader(reader);