changeset 106:d39f656b6614 embedded

Made several bug fixes from the tests.
author Pedro Ferreira <pedro.ferreira@monetdbsolutions.com>
date Fri, 20 Jan 2017 19:06:41 +0100 (2017-01-20)
parents d4c6a01cc300
children e026fe73bb5e
files src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java src/main/java/nl/cwi/monetdb/mcl/connection/mapi/AbstractSocket.java src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTableHeaderParser.java src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParserHelper.java src/main/java/nl/cwi/monetdb/mcl/responses/DataBlockResponse.java
diffstat 13 files changed, 85 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java
@@ -84,6 +84,8 @@ public abstract class MonetConnection ex
     private final boolean clobIsLongChar;
     /** The underlying proticol provided by the connection (MAPI or embedded) */
     protected AbstractProtocol protocol;
+    /** Tells if the connection is embedded or not */
+    private final boolean isEmbedded;
 
     /**
      * Constructor of a Connection for MonetDB. At this moment the current implementation limits itself to storing the
@@ -99,6 +101,8 @@ public abstract class MonetConnection ex
         this.language = language;
         this.blobIsBinary = blobIsBinary;
         this.clobIsLongChar = clobIsLongChar;
+        String embedded = props.getProperty("embedded");
+        this.isEmbedded = embedded != null && embedded.equals("true");
     }
 
     /**
@@ -183,18 +187,6 @@ public abstract class MonetConnection ex
     public abstract void sendControlCommand(int commandID, int data) throws SQLException;
 
     /**
-     * Creates a ResponseList.
-     *
-     * @param fetchSize the nubmer of rows per block in the response list
-     * @param maxRows maximum number of rows to allow in the set
-     * @param resultSetType the type of result sets to produce
-     * @param resultSetConcurrency the concurrency of result sets to produce
-     * @return A ResponseList instance
-     */
-    public abstract ResponseList createResponseList(int fetchSize, int maxRows, int resultSetType,
-                                                    int resultSetConcurrency);
-
-    /**
      * Releases this Connection object's database and JDBC resources immediately instead of waiting for them to be
      * automatically released. All Statements created from this Connection will be closed when this method is called.
      *
@@ -1498,8 +1490,10 @@ public abstract class MonetConnection ex
                  * Change the reply size of the server.  If the given value is the same as the current value known
                  * to use, then ignore this call.  If it is set to 0 we get a prompt after the server sent it's
                  * header.
+                 *
+                 * 2017: For now, in the embedded connection, the value set cachesize will be always the default one.
                  */
-                int size = cachesize == 0 ? MonetConnection.this.getDefFetchsize() : cachesize;
+                int size = (cachesize != 0 && !isEmbedded) ? cachesize : MonetConnection.this.getDefFetchsize();
                 size = maxrows != 0 ? Math.min(maxrows, size) : size;
                 // don't do work if it's not needed
                 if (language == MapiLanguage.LANG_SQL && size != curReplySize &&
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java.in
@@ -243,7 +243,7 @@ final public class MonetDriver implement
 		typeMap.put("double", Types.DOUBLE);
 		typeMap.put("geometry", Types.OTHER);
 		typeMap.put("geometrya", Types.OTHER);
-		typeMap.put("hugeint", Types.NUMERIC); //but we will convert to java.math.BigInteger
+		typeMap.put("hugeint", Types.NUMERIC);
 		typeMap.put("inet", Types.OTHER);
 		typeMap.put("int", Types.INTEGER);
 		typeMap.put("json", Types.OTHER);
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java
@@ -16,7 +16,6 @@ import java.io.InputStream;
 import java.io.Reader;
 import java.io.IOException;
 import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.math.RoundingMode;
 import java.net.URL;
 import java.nio.CharBuffer;
@@ -1659,18 +1658,6 @@ public class MonetPreparedStatement exte
 					setDouble(parameterIndex, val6);
 					break;
 				case Types.NUMERIC:
-					BigInteger val7;
-					try {
-						val7 = new BigInteger((String)x);
-					} catch (NumberFormatException e) {
-						try {
-							val7 = BigInteger.ZERO;
-						} catch (NumberFormatException ex) {
-							throw new SQLException("Internal error: unable to create template BigInteger: " + ex.getMessage(), "M0M03");
-						}
-					}
-					setObject(parameterIndex, val7);
-					break;
 				case Types.DECIMAL:
 					BigDecimal val8;
 					try {
@@ -1736,7 +1723,7 @@ public class MonetPreparedStatement exte
 				default:
 					throw new SQLException("Conversion not allowed", "M1M05");
 			}
-		} else if (x instanceof BigDecimal || x instanceof BigInteger || x instanceof Byte || x instanceof Short || x instanceof Integer || x instanceof Long || x instanceof Float || x instanceof Double) {
+		} else if (x instanceof BigDecimal || x instanceof Byte || x instanceof Short || x instanceof Integer || x instanceof Long || x instanceof Float || x instanceof Double) {
 			Number num = (Number)x;
 			switch (targetSqlType) {
 				case Types.TINYINT:
@@ -1758,12 +1745,6 @@ public class MonetPreparedStatement exte
 					setDouble(parameterIndex, num.doubleValue());
 					break;
 				case Types.NUMERIC:
-					if (x instanceof BigInteger) {
-						setObject(parameterIndex, x);
-					} else {
-						setObject(parameterIndex, new BigInteger(Integer.toString(num.intValue())));
-					}
-					break;
 				case Types.DECIMAL:
 					if (x instanceof BigDecimal) {
 						setBigDecimal(parameterIndex, (BigDecimal)x);
@@ -1808,8 +1789,6 @@ public class MonetPreparedStatement exte
 					setDouble(parameterIndex, (val ? 1.0 : 0.0));  // do no cast to (double) as it generates a compiler warning
 					break;
 				case Types.NUMERIC:
-					setObject(parameterIndex, val ? BigInteger.ONE : BigInteger.ZERO);
-					break;
 				case Types.DECIMAL:
 					setBigDecimal(parameterIndex, val ? BigDecimal.ONE : BigDecimal.ZERO);
 				 	break;
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java
@@ -17,7 +17,6 @@ import java.io.*;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.sql.Array;
@@ -93,7 +92,7 @@ public class MonetResultSet extends Mone
 	/** Just a dummy variable to keep store the fetchsize set. */
 	private int fetchSize;
 	/** The current row's values */
-	DataBlockResponse currentBlock;
+	private DataBlockResponse currentBlock;
 
 	/**
 	 * Main constructor backed by the given Header.
@@ -589,16 +588,12 @@ public class MonetResultSet extends Mone
 			}
 			BigDecimal val;
 			switch (JdbcSQLTypes[columnIndex - 1]) {
+				case Types.NUMERIC:
 				case Types.DECIMAL:
 					val = (BigDecimal) currentBlock.getObjectValue(columnIndex - 1);
 					break;
-				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					val = BigDecimal.valueOf(huge.longValue());
-					break;
 				case Types.BOOLEAN:
-					byte bval = currentBlock.getBooleanValue(columnIndex - 1) ? (byte) 1 : (byte) 0;
-					val = new BigDecimal(bval);
+					val = new BigDecimal(currentBlock.getBooleanValue(columnIndex - 1) ? (byte) 1 : (byte) 0);
 					break;
 				case Types.TINYINT:
 					val = new BigDecimal(currentBlock.getByteValue(columnIndex - 1));
@@ -739,8 +734,6 @@ public class MonetResultSet extends Mone
 						return true;
 					throw newSQLInvalidColumnIndexException(columnIndex);
 				case Types.NUMERIC:
-				    BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-                    return huge.compareTo(BigInteger.ZERO) != 0;
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.compareTo(BigDecimal.ZERO) != 0;
@@ -805,8 +798,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Byte.parseByte(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.byteValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.byteValue();
@@ -961,8 +952,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Double.parseDouble(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.doubleValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.doubleValue();
@@ -1106,8 +1095,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Float.parseFloat(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.floatValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.floatValue();
@@ -1173,8 +1160,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Integer.parseInt(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.intValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.intValue();
@@ -1239,8 +1224,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Long.parseLong(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.longValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.longValue();
@@ -1909,8 +1892,6 @@ public class MonetResultSet extends Mone
 		}
 		if (type == null || type == String.class) {
 			return currentBlock.getValueAsString(columnIndex - 1);
-		} else if (type == BigInteger.class) {
-			return getObject(columnIndex);
 		} else if (type == BigDecimal.class) {
 			return getBigDecimal(columnIndex);
 		} else if (type == Boolean.class) {
@@ -2198,7 +2179,6 @@ public class MonetResultSet extends Mone
 			case Types.LONGVARCHAR:
 				return String.class;
 			case Types.NUMERIC:
-				return BigInteger.class;
 			case Types.DECIMAL:
 				return BigDecimal.class;
 			case Types.BOOLEAN:
@@ -2356,8 +2336,6 @@ public class MonetResultSet extends Mone
 				case Types.LONGVARBINARY:
 					return Short.parseShort(currentBlock.getValueAsString(columnIndex - 1));
 				case Types.NUMERIC:
-					BigInteger huge = (BigInteger) currentBlock.getValueAsObject(columnIndex - 1);
-					return huge.shortValue();
 				case Types.DECIMAL:
 					BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1);
 					return bigdec.shortValue();
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
+++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java
@@ -196,9 +196,8 @@ public class MonetStatement extends Mone
 			for (int i = 0; i < batch.size(); i++) {
 				String tmp = batch.get(i);
 				if (sep.length() + tmp.length() > connection.getBlockSize()) {
-					// The thing is too big.  Way too big.  Since it won't
-					// be optimal anyway, just add it to whatever we have
-					// and continue.
+					// The thing is too big. Way too big. Since it won't be optimal anyway, just add it to whatever we
+					// have and continue.
 					if (!first) {
 						tmpBatch.append(sep);
 					}
@@ -475,7 +474,7 @@ public class MonetStatement extends Mone
 		}
 
 		// create a container for the result
-		lastResponseList = connection.createResponseList(fetchSize, maxRows, resultSetType, resultSetConcurrency);
+		lastResponseList = connection.new ResponseList(fetchSize, maxRows, resultSetType, resultSetConcurrency);
 		// fill the header list by processing the query
 		lastResponseList.processQuery(sql);
 
@@ -660,7 +659,7 @@ public class MonetStatement extends Mone
 	public ResultSet getGeneratedKeys() throws SQLException {
 		String[] columns = new String[1], types = new String[1];
 		int[] jdbcTypes = new int[1];
-		String[][] results;
+		Object[] results;
 
 		columns[0] = "GENERATED_KEY";
 		/* the generated key should be an integer, because (wait for it) other 
@@ -668,16 +667,13 @@ public class MonetStatement extends Mone
 		types[0] = "BIGINT";
 		jdbcTypes[0] = MonetDriver.getJavaType(types[0]);
 
+		results = new Object[1];
+		results[0] = new long[1];
+
 		if (header instanceof UpdateResponse) {
-			int lastid = ((UpdateResponse)header).getLastid();
-			if (lastid ==-1) {
-				results = new String[1][1];
-			} else {
-				results = new String[1][1];
-				results[0][0] = Integer.toString(lastid);
-			}
+			((long[]) results[0])[0] = ((UpdateResponse)header).getLastid();
 		} else {
-			results = new String[1][1];
+			((long[]) results[0])[0] = -1;
 		}
 
 		try {
@@ -1187,15 +1183,14 @@ public class MonetStatement extends Mone
  * TODO: try to eliminate the need for this class completely.
  */
 final class MonetVirtualResultSet extends MonetResultSet {
-	private String results[][];
+	private Object[] results;
 	private boolean closed;
 
-	MonetVirtualResultSet(Statement statement, String[] columns, String[] types, int[] jdbcTypes, String[][] results)
+	MonetVirtualResultSet(Statement statement, String[] columns, String[] types, int[] jdbcTypes, Object[] results)
 			throws IllegalArgumentException {
 		super(statement, columns, types, jdbcTypes, results.length);
 		this.results = results;
 		this.closed = false;
-        this.currentBlock.setData(results);
 	}
 
 	/**
@@ -1226,13 +1221,17 @@ final class MonetVirtualResultSet extend
 		this.curRow = row;
 
 		// see if we have the row
-		if (row < 1 || row > tupleCount) return false;
-
-		String[] values = (String[]) this.currentBlock.getData()[0];
+		return !(row < 1 || row > tupleCount);
+	}
 
-		System.arraycopy(this.results[row - 1], 0, values, 0, this.results[row - 1].length);
+	@Override
+	public int getInt(int column) throws SQLException {
+		return (int) ((long[]) results[0])[0];
+	}
 
-		return true;
+	@Override
+	public long getLong(int column) throws SQLException {
+		return ((long[]) results[0])[0];
 	}
 
 	/**
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/AbstractSocket.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/AbstractSocket.java
@@ -19,6 +19,7 @@ import java.nio.ByteOrder;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
 import java.nio.charset.StandardCharsets;
 
 /**
@@ -27,7 +28,7 @@ import java.nio.charset.StandardCharsets
  * fetched will be different hence this class should be sub-classed according to the protocol itself.
  * <br/>
  * Meanwhile the implementation of this class uses Java ByteBuffers which allows memory re-usage for more performance.
- * Also MonetDB uses UTF-8 as its character encoding, hence its required to convert into UTF-16 (JVM encoding).
+ * Also MonetDB uses UTF-8 as its character encoding, hence it is required to convert into UTF-16 (JVM encoding).
  *
  * @author Pedro Ferreira
  */
@@ -205,10 +206,19 @@ public abstract class AbstractSocket imp
     private void writeToOutputBuffer(boolean toFlush) throws IOException {
         this.stringsEncoded.flip();
         this.utf8Encoder.reset();
+        CoderResult res;
+        int written = 0;
+        do {
+            res = this.utf8Encoder.encode(this.stringsEncoded, this.bufferOut, false);
+            written += this.writeFromBufferOut(this.bufferOut);
+        } while (res == CoderResult.OVERFLOW);
+
         this.utf8Encoder.encode(this.stringsEncoded, this.bufferOut, true);
         this.utf8Encoder.flush(this.bufferOut);
+        written += this.writeFromBufferOut(this.bufferOut);
+
         this.stringsEncoded.clear();
-        int written = this.writeFromBufferOut(this.bufferOut);
+        this.bufferOut.clear();
         if(written == 0) {
             throw new IOException("The query could not be sent to the server!");
         } else {
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/connection/mapi/MapiConnection.java
@@ -255,20 +255,6 @@ public class MapiConnection extends Mone
     }
 
     /**
-     * Creates a ResponseList. In a Mapi connection, there are no restrictions while creating the response list.
-     *
-     * @param fetchSize the nubmer of rows per block in the response list
-     * @param maxRows maximum number of rows to allow in the set
-     * @param resultSetType the type of result sets to produce
-     * @param resultSetConcurrency the concurrency of result sets to produce
-     * @return A ResponseList instance
-     */
-    @Override
-    public ResponseList createResponseList(int fetchSize, int maxRows, int resultSetType, int resultSetConcurrency) {
-        return new MonetConnection.ResponseList(fetchSize, maxRows, resultSetType, resultSetConcurrency);
-    }
-
-    /**
      * Connects to the given host and port, logging in as the given user. If followRedirect is false, a
      * RedirectionException is thrown when a redirect is encountered.
      *
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java
@@ -157,7 +157,7 @@ public class OldMapiProtocol extends Abs
         int tuplecount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this);
         int columncount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this);
         int rowcount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this);
-        return new ResultSetResponse(con, list, seqnr, id, rowcount, tuplecount, columncount);
+        return new ResultSetResponse(con, list, id, seqnr, rowcount, tuplecount, columncount);
     }
 
     /**
@@ -181,7 +181,7 @@ public class OldMapiProtocol extends Abs
      */
     @Override
     public AutoCommitResponse getNextAutoCommitResponse() throws ProtocolException {
-        boolean ac = OldMapiStartOfHeaderParser.GetNextResponseDataAsString(this).equals("t");
+        boolean ac = this.lineBuffer.get() == 't';
         return new AutoCommitResponse(ac);
     }
 
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java
@@ -38,6 +38,7 @@ final class OldMapiStartOfHeaderParser {
                 break;
             case '4':
                 res = StarterHeaders.Q_TRANS;
+                protocol.lineBuffer.get();
                 break;
             case '5':
                 res = StarterHeaders.Q_PREPARE;
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTableHeaderParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTableHeaderParser.java
@@ -101,6 +101,11 @@ final class OldMapiTableHeaderParser {
     /**
      * Fills a String array header with values.
      *
+     * As of Oct2014-SP1 release MAPI adds double quotes around names when the name contains a comma or a tab or a space
+     * or a # or " character.
+     * See issue: https://www.monetdb.org/bugzilla/show_bug.cgi?id=3616 If the parsed name string part has a " as first
+     * and last character, we remove those added double quotes here.
+     *
      * @param array The lineBuffer's backing array
      * @param stop The position to stop parsing
      * @param stringValues The String array to fill
@@ -110,12 +115,18 @@ final class OldMapiTableHeaderParser {
 
         for (int i = start + 1; i < stop; i++) {
             if (array[i] == '\t' && array[i - 1] == ',') {
-                stringValues[elem++] = new String(array, start, i - 1 - start);
+                if (array[start] == '"') {
+                    start++;  // skip leading double quote
+                }
+                stringValues[elem++] = new String(array, start, i - (array[i - 2] == '"' ? 2 : 1) - start);
                 start = i + 1;
             }
         }
-        // add the left over part
-        stringValues[elem] = new String(array, start, stop - start);
+        // add the left over part (last column)
+        if (array[start] == '"') {
+            start++;  // skip leading double quote
+        }
+        stringValues[elem] = new String(array, start, stop - (array[stop - 1] == '"' ? 1 : 0) - start);
     }
 
     /**
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java
@@ -146,6 +146,8 @@ final class OldMapiTupleLineParser {
                                             tupleLineBuffer.put(array[pos]);
                                             break;
                                     }
+                                } else if(array[pos] == '\\') {
+
                                 } else {
                                     tupleLineBuffer.put(array[pos]);
                                 }
@@ -153,7 +155,7 @@ final class OldMapiTupleLineParser {
                             // put the unescaped string in the right place
                             tupleLineBuffer.flip();
                             OldMapiStringToJavaDataConversion(tupleLineBuffer.array(), 0, tupleLineBuffer.limit(), lineNumber, values[column], typesMap[column]);
-                        } else if ((i - 1) - cursor == 4 && OldMapiTupleLineParserHelper.CharIndexOf(array, array.length, NULL_STRING, 4) == cursor) {
+                        } else if ((i - 1) - cursor == 4 && OldMapiTupleLineParserHelper.CharIndexOf(array, 0, array.length, NULL_STRING, 0,4, cursor) == cursor) {
                             SetNullValue(lineNumber, values[column], typesMap[column]);
                         } else {
                             OldMapiStringToJavaDataConversion(array, cursor, i - 1 - cursor, lineNumber, values[column], typesMap[column]);
@@ -206,7 +208,7 @@ final class OldMapiTupleLineParser {
                                                           Object columnArray, int jDBCMapping) throws ProtocolException {
         switch (jDBCMapping) {
             case Types.BOOLEAN:
-                ((byte[]) columnArray)[lineNumber] = OldMapiTupleLineParserHelper.CharArrayToBoolean(toParse, startPosition, count);
+                ((byte[]) columnArray)[lineNumber] = OldMapiTupleLineParserHelper.CharArrayToBoolean(toParse, startPosition);
                 break;
             case Types.TINYINT:
                 ((byte[]) columnArray)[lineNumber] = OldMapiTupleLineParserHelper.CharArrayToByte(toParse, startPosition, count);
@@ -226,12 +228,10 @@ final class OldMapiTupleLineParser {
             case Types.DOUBLE:
                 ((double[]) columnArray)[lineNumber] = Double.parseDouble(new String(toParse, startPosition, count));
                 break;
+            case Types.NUMERIC:
             case Types.DECIMAL:
                 ((BigDecimal[]) columnArray)[lineNumber] = new BigDecimal(toParse, startPosition, count);
                 break;
-            case Types.NUMERIC:
-                ((BigInteger[]) columnArray)[lineNumber] = new BigInteger(new String(toParse, startPosition, count));
-                break;
             case Types.CHAR:
             case Types.VARCHAR:
             case Types.LONGVARCHAR:
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParserHelper.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParserHelper.java
@@ -30,29 +30,34 @@ final class OldMapiTupleLineParserHelper
      * @param targetCount The result set column SQL types
      * @return The integer representation of the Table Result Header retrieved
      */
-    static int CharIndexOf(char[] source, int sourceCount, char[] target, int targetCount) {
+    static int CharIndexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset,
+                           int targetCount, int fromIndex) {
+        if (fromIndex >= sourceCount) {
+            return (targetCount == 0 ? sourceCount : -1);
+        }
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        }
         if (targetCount == 0) {
-            return 0;
+            return fromIndex;
         }
 
-        char first = target[0];
-        int max = sourceCount - targetCount;
+        char first = target[targetOffset];
+        int max = sourceOffset + (sourceCount - targetCount);
 
-        for (int i = 0; i <= max; i++) {
+        for (int i = sourceOffset + fromIndex; i <= max; i++) {
             /* Look for first character. */
             if (source[i] != first) {
                 while (++i <= max && source[i] != first);
             }
-
-            /* Found first character, now look at the rest of v2 */
             if (i <= max) {
                 int j = i + 1;
                 int end = j + targetCount - 1;
-                for (int k = 1; j < end && source[j] == target[k]; j++, k++);
+                for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++);
 
                 if (j == end) {
                     /* Found whole string. */
-                    return i;
+                    return i - sourceOffset;
                 }
             }
         }
@@ -67,13 +72,12 @@ final class OldMapiTupleLineParserHelper
     /**
      * Converts a segment of a CharBuffer's backing array into a Java boolean.
      *
+     * @param start The first position in the array to parse
      * @param data The CharBuffer's backing array to parse
-     * @param start The first position in the array to parse
-     * @param count The number of characters to read from the starter position
      * @return 1 it's a true value, 0 if false
      */
-    static byte CharArrayToBoolean(char[] data, int start, int count) {
-        return CharIndexOf(data, start + count, TrueConstant, 4) == start ? (byte)1 : (byte)0;
+    static byte CharArrayToBoolean(char[] data, int start) {
+        return CharIndexOf(data, 0, data.length, TrueConstant, 0, 4, start) == start ? (byte)1 : (byte)0;
     }
 
     /**
--- a/src/main/java/nl/cwi/monetdb/mcl/responses/DataBlockResponse.java
+++ b/src/main/java/nl/cwi/monetdb/mcl/responses/DataBlockResponse.java
@@ -15,7 +15,6 @@ import nl.cwi.monetdb.mcl.protocol.Proto
 import nl.cwi.monetdb.mcl.protocol.ServerResponses;
 
 import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.sql.Types;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -104,12 +103,10 @@ public class DataBlockResponse implement
                     case Types.DOUBLE:
                         this.data[i] = new double[this.rowcount];
                         break;
+                    case Types.NUMERIC:
                     case Types.DECIMAL:
                         this.data[i] = new BigDecimal[this.rowcount];
                         break;
-                    case Types.NUMERIC:
-                        this.data[i] = new BigInteger[this.rowcount];
-                        break;
                     case Types.BLOB:
                         this.data[i] = new MonetBlob[this.rowcount];
                         break;
@@ -173,26 +170,6 @@ public class DataBlockResponse implement
     }
 
     /**
-     * Sets the data on the block.
-     * This method is called by the MonetVirtualResultSet class which should be eliminated on the future.
-     *
-     * @param data the data to set
-     */
-    public void setData(Object[] data) { /* For VirtualResultSet :( */
-        this.data = data;
-    }
-
-    /**
-     * Gets the data on the block.
-     * This method is called by the MonetVirtualResultSet class which should be eliminated on the future.
-     *
-     * @return the result set data
-     */
-    public Object[] getData() { /* For VirtualResultSet :( */
-        return this.data;
-    }
-
-    /**
      * Checks if a value in the current row is null.
      *
      * @param column The column index starting from 0
@@ -327,7 +304,7 @@ public class DataBlockResponse implement
                 return Float.toString(((float[]) this.data[column])[this.blockLine]);
             case Types.DOUBLE:
                 return Double.toString(((double[]) this.data[column])[this.blockLine]);
-            default: //BLOB, CLOB, BigDecimal, BigInteger, Time, Timestamp and Date
+            default: //BLOB, CLOB, BigDecimal, Time, Timestamp and Date
                 return ((Object[]) this.data[column])[this.blockLine].toString();
         }
     }