Mercurial > hg > monetdb-java
changeset 68:86967be24645 embedded
Ready to start testing the old mapi connection. After passing the tests. The embedded integration will be very straightforward.
line wrap: on
line diff
--- a/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java +++ b/src/main/java/nl/cwi/monetdb/embedded/env/MonetDBEmbeddedConnection.java @@ -215,7 +215,7 @@ public class MonetDBEmbeddedConnection { /** * When the database is shuts down, this method is called instead */ - public void closeConnectionImplementation() { + void closeConnectionImplementation() { for(AbstractConnectionResult res : this.results.values()) { res.closeImplementation(); } @@ -240,7 +240,7 @@ public class MonetDBEmbeddedConnection { /** * Removes a query result from this connection. */ - protected void removeQueryResult(AbstractConnectionResult res) { this.results.remove(res.getRandomIdentifier()); } + void removeQueryResult(AbstractConnectionResult res) { this.results.remove(res.getRandomIdentifier()); } /** * Internal implementation of sendUpdate.
deleted file mode 100644 --- a/src/main/java/nl/cwi/monetdb/embedded/mapping/MonetDBEmbeddedBlob.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 2016 MonetDB B.V. - */ - -package nl.cwi.monetdb.embedded.mapping; - -import java.io.*; -import java.sql.Blob; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; - -/** - * A Java representation for the BLOB data type. Added for more efficient data mapping when fetching from the database. - * - * @author <a href="mailto:pedro.ferreira@monetdbsolutions.com">Pedro Ferreira</a> - */ -public class MonetDBEmbeddedBlob implements Serializable, Blob, Comparable<MonetDBEmbeddedBlob> { - - /** - * The BLOB's content as a Java byte array. - */ - private byte[] blob; - - public MonetDBEmbeddedBlob(byte[] blob) { this.blob = blob; } - - /** - * Get the BLOB content itself, - * - * @return A Java byte array containing the BLOB itself - */ - public byte[] getBlob() { return this.blob; } - - /** - * Overriding the equals method for the byte array. - */ - @Override - public boolean equals(Object obj) { - return obj instanceof MonetDBEmbeddedBlob && Arrays.equals(this.blob, ((MonetDBEmbeddedBlob) obj).getBlob()); - } - - /** - * Overriding the hashCode method for the byte array. - */ - @Override - public int hashCode() { return Arrays.hashCode(this.blob); } - - /** - * Overriding the toString method for the byte array. - */ - @Override - public String toString() { return Arrays.toString(blob); } - - private void checkFreed() throws SQLException { - if(this.blob == null) { - throw new SQLException("Thsi blob was freed!"); - } - } - - @Override - public long length() throws SQLException { - this.checkFreed(); - return this.blob.length; - } - - @Override - public byte[] getBytes(long pos, int length) throws SQLException { - this.checkFreed(); - return Arrays.copyOfRange(this.blob, (int) pos, length); - } - - @Override - public InputStream getBinaryStream() throws SQLException { - this.checkFreed(); - return new ByteArrayInputStream(this.blob); - } - - @Override - public long position(byte[] pattern, long start) throws SQLException { - this.checkFreed(); - byte[] subArray = Arrays.copyOfRange(this.blob, (int)start, pattern.length); - return Collections.indexOfSubList(Arrays.asList(subArray), Arrays.asList(pattern)); - } - - @Override - public long position(Blob pattern, long start) throws SQLException { - this.checkFreed(); - byte[] subArray = Arrays.copyOfRange(this.blob, (int)start, (int) pattern.length()); - return Collections.indexOfSubList(Arrays.asList(subArray), Arrays.asList(pattern.getBytes(0, (int)pattern.length()))); - } - - @Override - public int setBytes(long pos, byte[] bytes) throws SQLException { - this.checkFreed(); - int newFinalLength = (int) pos + bytes.length; - byte[] newblob; - - if(newFinalLength > this.blob.length) { - newblob = new byte[newFinalLength]; - } else { - newblob = this.blob; - } - System.arraycopy(bytes, 0, newblob, (int) pos, bytes.length); - this.blob = newblob; - return bytes.length; - } - - @Override - public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { - this.checkFreed(); - int newFinalLength = (int) pos + len; - byte[] newblob; - - if(newFinalLength > this.blob.length) { - newblob = new byte[newFinalLength]; - } else { - newblob = this.blob; - } - System.arraycopy(bytes, offset, newblob, (int) pos, len); - this.blob = newblob; - return bytes.length; - } - - @Override - public OutputStream setBinaryStream(long pos) throws SQLException { - this.checkFreed(); - ByteArrayOutputStream res = null; - try { - res = new ByteArrayOutputStream(); - res.write(this.blob); - } catch (IOException e) { - throw new SQLException(e); - } - return res; - } - - @Override - public void truncate(long len) throws SQLException { - this.checkFreed(); - byte[] newblob = new byte[(int)len]; - System.arraycopy(this.blob, 0, newblob, 0, (int)len); - this.blob = newblob; - } - - @Override - public void free() throws SQLException { - this.blob = null; - } - - @Override - public InputStream getBinaryStream(long pos, long length) throws SQLException { - this.checkFreed(); - return new ByteArrayInputStream(Arrays.copyOfRange(this.blob, (int) pos, (int) length)); - } - - @Override - public int compareTo(MonetDBEmbeddedBlob o) { - byte[] first = this.blob, second = o.blob; - int len = Math.min(first.length, second.length), res = 0; - for(int i = 0; i < len ; i++) { - res = res + first[i] - second[i]; - } - return res; - } -}
--- a/src/main/java/nl/cwi/monetdb/embedded/mapping/MonetDBRow.java +++ b/src/main/java/nl/cwi/monetdb/embedded/mapping/MonetDBRow.java @@ -28,7 +28,7 @@ public class MonetDBRow implements Itera */ private Object[] columns; - protected MonetDBRow(AbstractRowSet originalSet, Object[] columns) { + MonetDBRow(AbstractRowSet originalSet, Object[] columns) { this.originalSet = originalSet; this.columns = columns; }
--- a/src/main/java/nl/cwi/monetdb/embedded/mapping/MonetDBToJavaMapping.java +++ b/src/main/java/nl/cwi/monetdb/embedded/mapping/MonetDBToJavaMapping.java @@ -8,6 +8,8 @@ package nl.cwi.monetdb.embedded.mapping; +import nl.cwi.monetdb.jdbc.MonetBlob; + import java.math.BigDecimal; import java.math.BigInteger; import java.net.Inet4Address; @@ -31,9 +33,8 @@ public enum MonetDBToJavaMapping { Tinyint(Byte.class), Smallint(Short.class), Int(Integer.class), Wrd(Long.class), Bigint(Long.class), Hugeint(BigInteger.class), Decimal(BigDecimal.class), Real(Float.class), Double(Double.class), MonthInterval(Integer.class), SecondInterval(Long.class), Time(Time.class), TimeTz(Time.class), Date(Date.class), - Timestamp(Timestamp.class), TimestampTz(Timestamp.class), Blob(MonetDBEmbeddedBlob.class), - Geometry(MonetDBEmbeddedBlob.class), GeometryA(MonetDBEmbeddedBlob.class), URL(URL.class), Inet(Inet4Address.class), - JSON(MonetDBEmbeddedBlob.class), UUID(UUID.class); + Timestamp(Timestamp.class), TimestampTz(Timestamp.class), Blob(MonetBlob.class), Geometry(String.class), + GeometryA(String.class), URL(URL.class), Inet(Inet4Address.class), JSON(String.class), UUID(UUID.class); /** * The mapping between MonetDB data types and enum values. @@ -98,12 +99,12 @@ public enum MonetDBToJavaMapping { AppendMappings.put(Date, Date[].class); AppendMappings.put(Timestamp, Timestamp[].class); AppendMappings.put(TimestampTz, Timestamp[].class); - AppendMappings.put(Blob, MonetDBEmbeddedBlob[].class); - AppendMappings.put(Geometry, MonetDBEmbeddedBlob[].class); - AppendMappings.put(GeometryA, MonetDBEmbeddedBlob[].class); + AppendMappings.put(Blob, MonetBlob[].class); + AppendMappings.put(Geometry, String[].class); + AppendMappings.put(GeometryA, String[].class); AppendMappings.put(URL, URL[].class); AppendMappings.put(Inet, Inet4Address[].class); - AppendMappings.put(JSON, MonetDBEmbeddedBlob[].class); + AppendMappings.put(JSON, String[].class); AppendMappings.put(UUID, UUID[].class); }
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/AbstractQueryResultSetColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/AbstractQueryResultSetColumn.java @@ -37,12 +37,12 @@ public abstract class AbstractQueryResul /** * The index of the first value mapped to a Java class. */ - protected int firstRetrievedIndex; + private int firstRetrievedIndex; /** * The index of the last value mapped to a Java class. */ - protected int lastRetrievedIndex; + private int lastRetrievedIndex; protected AbstractQueryResultSetColumn(String columnType, long tablePointer, int resultSetIndex, String columnName, int columnDigits, int columnScale, int numberOfRows) { @@ -55,6 +55,15 @@ public abstract class AbstractQueryResul } /** + * Gets the result set index of the column. + * + * @return The result set index of the column + */ + public int getResultSetIndex() { + return resultSetIndex; + } + + /** * Gets the number of rows in this column. * * @return The number of rows
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultRowSet.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultRowSet.java @@ -23,7 +23,7 @@ import java.util.ListIterator; */ public class QueryResultRowSet extends AbstractRowSet implements Iterable { - protected QueryResultRowSet(QueryResultSet queryResultSet, MonetDBToJavaMapping[] mappings, Object[][] rows) { + QueryResultRowSet(QueryResultSet queryResultSet, MonetDBToJavaMapping[] mappings, Object[][] rows) { super(queryResultSet, mappings, rows); }
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetBooleanColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetBooleanColumn.java @@ -61,7 +61,8 @@ public final class QueryResultSetBoolean } @Override - protected boolean[] checkIfIndexesAreNullImplementation(boolean[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(boolean[] values, boolean[] res) + throws MonetDBEmbeddedException { boolean nil = GetBooleanNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetByteColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetByteColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetByteCol } @Override - protected boolean[] checkIfIndexesAreNullImplementation(byte[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(byte[] values, boolean[] res) + throws MonetDBEmbeddedException { byte nil = GetByteNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetDoubleColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetDoubleColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetDoubleC } @Override - protected boolean[] checkIfIndexesAreNullImplementation(double[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(double[] values, boolean[] res) + throws MonetDBEmbeddedException { double nil = GetDoubleNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetFloatColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetFloatColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetFloatCo } @Override - protected boolean[] checkIfIndexesAreNullImplementation(float[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(float[] values, boolean[] res) + throws MonetDBEmbeddedException { float nil = GetFloatNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetIntColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetIntColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetIntColu } @Override - protected boolean[] checkIfIndexesAreNullImplementation(int[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(int[] values, boolean[] res) + throws MonetDBEmbeddedException { int nil = GetIntNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetLongColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetLongColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetLongCol } @Override - protected boolean[] checkIfIndexesAreNullImplementation(long[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(long[] values, boolean[] res) + throws MonetDBEmbeddedException { long nil = GetLongNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetShortColumn.java +++ b/src/main/java/nl/cwi/monetdb/embedded/resultset/QueryResultSetShortColumn.java @@ -60,7 +60,8 @@ public final class QueryResultSetShortCo } @Override - protected boolean[] checkIfIndexesAreNullImplementation(short[] values, boolean[] res) throws MonetDBEmbeddedException { + protected boolean[] checkIfIndexesAreNullImplementation(short[] values, boolean[] res) + throws MonetDBEmbeddedException { short nil = GetShortNullConstant(); for(int i = 0 ; i < values.length ; i++) { res[i] = (values[i] == nil);
--- a/src/main/java/nl/cwi/monetdb/embedded/tables/MonetDBTable.java +++ b/src/main/java/nl/cwi/monetdb/embedded/tables/MonetDBTable.java @@ -156,8 +156,8 @@ public final class MonetDBTable extends public int iterateTable(IMonetDBTableCursor cursor) throws MonetDBEmbeddedException { int[] limits = this.prepareIterator(cursor); int res = 0, total = limits[1] - limits[0]; - String query = new StringBuffer("SELECT * FROM ").append(this.getTableSchema()).append(".").append(this.getTableName()) - .append(" LIMIT ").append(total).append(" OFFSET ").append(limits[0]).append(";").toString(); + String query = "SELECT * FROM " + this.getTableSchema() + "." + this.getTableName() + " LIMIT " + total + + " OFFSET " + limits[0] + ";"; QueryResultSet eqr = this.getConnection().sendQuery(query); MonetDBRow[] array = eqr.fetchAllRowValues().getAllRows();
--- a/src/main/java/nl/cwi/monetdb/embedded/tables/RowIterator.java +++ b/src/main/java/nl/cwi/monetdb/embedded/tables/RowIterator.java @@ -22,19 +22,19 @@ public class RowIterator extends Abstrac /** * The current table row number on the fetched set. */ - protected int currentIterationNumber = 0; + private int currentIterationNumber = 0; /** * The first row in the table to iterate. */ - protected final int firstIndex; + private final int firstIndex; /** * The last row in the table to iterate. */ - protected final int lastIndex; + private final int lastIndex; - protected RowIterator(MonetDBTable table, Object[][] rows, int firstIndex, int lastIndex) { + RowIterator(MonetDBTable table, Object[][] rows, int firstIndex, int lastIndex) { super(table, table.getMappings(), rows); this.firstIndex = firstIndex; this.lastIndex = lastIndex;
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetBlob.java @@ -22,141 +22,117 @@ import java.io.*; * * @author Fabian Groffen */ -public class MonetBlob implements Blob { +public class MonetBlob implements Blob, Serializable, Comparable<MonetBlob> { - private byte[] buf; + private byte[] buffer; - MonetBlob(byte[] buf) { - this.buf = buf; + public MonetBlob(byte[] buf) { + this.buffer = buf; } - MonetBlob(String in) { - int len = in.length() / 2; - this.buf = new byte[len]; - for (int i = 0; i < len; i++) { - this.buf[i] = (byte) Integer.parseInt(in.substring(2 * i, (2 * i) + 2), 16); - } + public byte[] getBuffer() { + return buffer; } //== begin interface Blob - + /** - * This method frees the Blob object and releases the resources that - * it holds. The object is invalid once the free method is called. + * This method frees the Blob object and releases the resources that it holds. The object is invalid once the + * free method is called. * - * After free has been called, any attempt to invoke a method other - * than free will result in a SQLException being thrown. If free is - * called multiple times, the subsequent calls to free are treated - * as a no-op. + * After free has been called, any attempt to invoke a method other than free will result in a SQLException being + * thrown. If free is called multiple times, the subsequent calls to free are treated as a no-op. * - * @throws SQLException if an error occurs releasing the Blob's - * resources - * @throws SQLFeatureNotSupportedException - if the JDBC driver does - * not support this method + * @throws SQLException if an error occurs releasing the Blob's resources + * @throws SQLFeatureNotSupportedException - if the JDBC driver does not support this method */ @Override public void free() throws SQLException { - buf = null; + buffer = null; } - + /** - * Retrieves the BLOB value designated by this Blob instance as a - * stream. + * Retrieves the BLOB value designated by this Blob instance as a stream. * * @return a stream containing the BLOB data * @throws SQLException if there is an error accessing the BLOB value - * @throws SQLFeatureNotSupportedException if the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method */ @Override public InputStream getBinaryStream() throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); - return new ByteArrayInputStream(buf); + return new ByteArrayInputStream(buffer); } /** - * Returns an InputStream object that contains a partial Blob value, - * starting with the byte specified by pos, which is length bytes in - * length. + * Returns an InputStream object that contains a partial Blob value, starting with the byte specified by pos, + * which is length bytes in length. * - * @param pos the offset to the first byte of the partial value to - * be retrieved. The first byte in the Blob is at position 1 - * @param length the length in bytes of the partial value to be - * retrieved - * @return InputStream through which the partial Blob value can be - * read. - * @throws SQLException if pos is less than 1 or if pos is - * greater than the number of bytes in the Blob or if pos + - * length is greater than the number of bytes in the Blob - * @throws SQLFeatureNotSupportedException if the JDBC driver does - * not support this method + * @param pos the offset to the first byte of the partial value to be retrieved. The first byte in the Blob is at + * position 1 + * @param length the length in bytes of the partial value to be retrieved + * @return InputStream through which the partial Blob value can be read. + * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes in the Blob or if pos + + * length is greater than the number of bytes in the Blob + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method */ @Override public InputStream getBinaryStream(long pos, long length) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); if (pos < 1) throw new SQLException("pos is less than 1", "M1M05"); - if (pos - 1 > buf.length) + if (pos - 1 > buffer.length) throw new SQLException("pos is greater than the number of bytes in the Blob", "M1M05"); - if (pos - 1 + length > buf.length) + if (pos - 1 + length > buffer.length) throw new SQLException("pos + length is greater than the number of bytes in the Blob", "M1M05"); - return new ByteArrayInputStream(buf, (int)(pos - 1), (int)length); + return new ByteArrayInputStream(buffer, (int)(pos - 1), (int)length); } /** - * Retrieves all or part of the BLOB value that this Blob object - * represents, as an array of bytes. This byte array contains up to - * length consecutive bytes starting at position pos. + * Retrieves all or part of the BLOB value that this Blob object represents, as an array of bytes. This byte array + * contains up to length consecutive bytes starting at position pos. * - * @param pos the ordinal position of the first byte in the BLOB - * value to be extracted; the first byte is at position 1. + * @param pos the ordinal position of the first byte in the BLOB value to be extracted; the first byte is at + * position 1. * @param length the number of consecutive bytes to be copied - * @return a byte array containing up to length consecutive bytes - * from the BLOB value designated by this Blob object, - * starting with the byte at position pos. - * @throws SQLException if there is an error accessing the - * BLOB value + * @return a byte array containing up to length consecutive bytes from the BLOB value designated by this Blob + * object, starting with the byte at position pos. + * @throws SQLException if there is an error accessing the BLOB value */ @Override public byte[] getBytes(long pos, int length) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); try { - return Arrays.copyOfRange(buf, (int) pos - 1, (int) pos - 1 + length); + return Arrays.copyOfRange(buffer, (int) pos - 1, (int) pos - 1 + length); } catch (IndexOutOfBoundsException e) { throw new SQLException(e.getMessage(), "M0M10"); } } /** - * Returns the number of bytes in the BLOB value designated by this - * Blob object. + * Returns the number of bytes in the BLOB value designated by this Blob object. * * @return length of the BLOB in bytes - * @throws SQLException if there is an error accessing the length - * of the BLOB value + * @throws SQLException if there is an error accessing the length of the BLOB value */ @Override public long length() throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); - return (long)buf.length; + return (long) buffer.length; } /** - * Retrieves the byte position in the BLOB value designated by this - * Blob object at which pattern begins. The search begins at - * position start. + * Retrieves the byte position in the BLOB value designated by this Blob object at which pattern begins. The search + * begins at position start. * - * @param pattern the Blob object designating the BLOB value for - * which to search - * @param start the position in the BLOB value at which to begin - * searching; the first position is 1 + * @param pattern the Blob object designating the BLOB value for which to search + * @param start the position in the BLOB value at which to begin searching; the first position is 1 * @return the position at which the pattern begins, else -1 - * @throws SQLException if there is an error accessing the - * BLOB value + * @throws SQLException if there is an error accessing the BLOB value */ @Override public long position(Blob pattern, long start) throws SQLException { @@ -164,26 +140,23 @@ public class MonetBlob implements Blob { } /** - * Retrieves the byte position at which the specified byte array - * pattern begins within the BLOB value that this Blob object - * represents. The search for pattern begins at position start. + * Retrieves the byte position at which the specified byte array pattern begins within the BLOB value that this + * Blob object represents. The search for pattern begins at position start. * * @param pattern the byte array for which to search - * @param start the position at which to begin searching; - * the first position is 1 + * @param start the position at which to begin searching; the first position is 1 * @return the position at which the pattern appears, else -1 - * @throws SQLException if there is an error accessing the - * BLOB value + * @throws SQLException if there is an error accessing the BLOB value */ @Override public long position(byte[] pattern, long start) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); try { - for (int i = (int)(start - 1); i < buf.length - pattern.length; i++) { + for (int i = (int)(start - 1); i < buffer.length - pattern.length; i++) { int j; for (j = 0; j < pattern.length; j++) { - if (buf[i + j] != pattern[j]) + if (buffer[i + j] != pattern[j]) break; } if (j == pattern.length) @@ -204,22 +177,19 @@ public class MonetBlob implements Blob { * the length of the Blob value will be increased to accomodate the * extra bytes. * - * @param pos the position in the BLOB value at which to start - * writing; the first position is 1 - * @return a java.io.OutputStream object to which data can be - * written - * @throws SQLException if there is an error accessing the BLOB - * value or if pos is less than 1 - * @throws SQLFeatureNotSupportedException if the JDBC driver does - * not support this method + * @param pos the position in the BLOB value at which to start writing; the first position is 1 + * @return a java.io.OutputStream object to which data can be written + * @throws SQLException if there is an error accessing the BLOB value or if pos is less than 1 + * @throws SQLFeatureNotSupportedException if the JDBC driver does not support this method */ @Override public OutputStream setBinaryStream(long pos) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); if (pos < 1) throw new SQLException("pos is less than 1", "M1M05"); - throw new SQLFeatureNotSupportedException("Operation setBinaryStream(long pos) currently not supported", "0A000"); + throw new SQLFeatureNotSupportedException("Operation setBinaryStream(long pos) currently not supported", + "0A000"); } /** @@ -227,13 +197,10 @@ public class MonetBlob implements Blob { * object represents, starting at position pos, and returns the * number of bytes written. * - * @param pos the position in the BLOB object at which to start - * writing - * @param bytes the array of bytes to be written to the BLOB value - * that this Blob object represents + * @param pos the position in the BLOB object at which to start writing + * @param bytes the array of bytes to be written to the BLOB value that this Blob object represents * @return the number of bytes written - * @throws SQLException if there is an error accessing the - * BLOB value + * @throws SQLException if there is an error accessing the BLOB value */ @Override public int setBytes(long pos, byte[] bytes) throws SQLException { @@ -246,25 +213,20 @@ public class MonetBlob implements Blob { * written. Writing starts at position pos in the BLOB value; len * bytes from the given byte array are written. * - * @param pos the position in the BLOB object at which to start - * writing - * @param bytes the array of bytes to be written to this BLOB - * object - * @param offset the offset into the array bytes at which to start - * reading the bytes to be set - * @param len the number of bytes to be written to the BLOB value - * from the array of bytes bytes + * @param pos the position in the BLOB object at which to start writing + * @param bytes the array of bytes to be written to this BLOB object + * @param offset the offset into the array bytes at which to start reading the bytes to be set + * @param len the number of bytes to be written to the BLOB value from the array of bytes bytes * @return the number of bytes written - * @throws SQLException if there is an error accessing the - * BLOB value + * @throws SQLException if there is an error accessing the BLOB value */ @Override public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); try { /* transactions? what are you talking about? */ - System.arraycopy(bytes, offset - 1 + (int) pos, buf, (int) pos, len - (int) pos); + System.arraycopy(bytes, offset - 1 + (int) pos, buffer, (int) pos, len - (int) pos); } catch (IndexOutOfBoundsException e) { throw new SQLException(e.getMessage(), "M0M10"); } @@ -272,22 +234,49 @@ public class MonetBlob implements Blob { } /** - * Truncates the BLOB value that this Blob object represents to be - * len bytes in length. + * Truncates the BLOB value that this Blob object represents to be len bytes in length. * - * @param len the length, in bytes, to which the BLOB value - * should be truncated - * @throws SQLException if there is an error accessing the - * BLOB value + * @param len the length, in bytes, to which the BLOB value should be truncated + * @throws SQLException if there is an error accessing the BLOB value */ @Override public void truncate(long len) throws SQLException { - if (buf == null) + if (buffer == null) throw new SQLException("This Blob object has been freed", "M1M20"); - if (buf.length > len) { + if (buffer.length > len) { byte[] newbuf = new byte[(int)len]; - System.arraycopy(buf, 0, newbuf, 0, (int) len); - buf = newbuf; + System.arraycopy(buffer, 0, newbuf, 0, (int) len); + buffer = newbuf; } } + + /** + * Overriding the equals method for the byte array. + */ + @Override + public boolean equals(Object obj) { + return obj instanceof MonetBlob && Arrays.equals(this.buffer, ((MonetBlob) obj).buffer); + } + + /** + * Overriding the hashCode method for the byte array. + */ + @Override + public int hashCode() { return Arrays.hashCode(this.buffer); } + + /** + * Overriding the toString method for the byte array. + */ + @Override + public String toString() { return Arrays.toString(this.buffer); } + + @Override + public int compareTo(MonetBlob o) { + byte[] first = this.buffer, second = o.buffer; + int len = Math.min(first.length, second.length), res = 0; + for(int i = 0; i < len ; i++) { + res = res + first[i] - second[i]; + } + return res; + } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetClob.java @@ -22,38 +22,33 @@ import java.io.*; * * @author Fabian Groffen */ -public class MonetClob implements Clob { +public class MonetClob implements Clob, Serializable, Comparable<MonetClob> { - private StringBuilder buf; + private final StringBuilder buffer; - MonetClob(String in) { - buf = new StringBuilder(in); + public MonetClob(String in) { + buffer = new StringBuilder(in); } //== begin interface Clob /** - * This method frees the Clob object and releases the resources the - * resources that it holds. The object is invalid once the free - * method is called. + * This method frees the Clob object and releases the resources the resources that it holds. The object is invalid + * once the free method is called. * - * After free has been called, any attempt to invoke a method other - * than free will result in a SQLException being thrown. If free is - * called multiple times, the subsequent calls to free are treated - * as a no-op. + * After free has been called, any attempt to invoke a method other than free will result in a SQLException being + * thrown. If free is called multiple times, the subsequent calls to free are treated as a no-op. */ @Override public void free() { - buf = null; + buffer.setLength(0); } /** - * Retrieves the CLOB value designated by this Clob object as an - * ascii stream. + * Retrieves the CLOB value designated by this Clob object as an ascii stream. * * @return a java.io.InputStream object containing the CLOB data - * @throws SQLFeatureNotSupportedException this JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException this JDBC driver does not support this method */ @Override public InputStream getAsciiStream() throws SQLException { @@ -61,12 +56,11 @@ public class MonetClob implements Clob { } /** - * Retrieves the CLOB value designated by this Clob object as a - * java.io.Reader object (or as a stream of characters). + * Retrieves the CLOB value designated by this Clob object as a java.io.Reader object + * (or as a stream of characters). * * @return a java.io.Reader object containing the CLOB data - * @throws SQLFeatureNotSupportedException this JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException this JDBC driver does not support this method */ @Override public Reader getCharacterStream() throws SQLException { @@ -74,75 +68,62 @@ public class MonetClob implements Clob { } /** - * Returns a Reader object that contains a partial Clob value, - * starting with the character specified by pos, which is length - * characters in length. + * Returns a Reader object that contains a partial Clob value, starting with the character specified by pos, which + * is length characters in length. * - * @param pos the offset to the first character of the partial value - * to be retrieved. The first character in the Clob is at - * position 1. - * @param length the length in characters of the partial value to be - * retrieved. + * @param pos the offset to the first character of the partial value to be retrieved. The first character in the + * Clob is at position 1. + * @param length the length in characters of the partial value to be retrieved. * @return Reader through which the partial Clob value can be read. - * @throws SQLFeatureNotSupportedException this JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException this JDBC driver does not support this method */ @Override public Reader getCharacterStream(long pos, long length) throws SQLException { - throw new SQLFeatureNotSupportedException("Operation getCharacterStream(long, long) currently not supported", "0A000"); + throw new SQLFeatureNotSupportedException("Operation getCharacterStream(long, long) currently not supported", + "0A000"); } /** - * Retrieves a copy of the specified substring in the CLOB value - * designated by this Clob object. The substring begins at - * position pos and has up to length consecutive characters. + * Retrieves a copy of the specified substring in the CLOB value designated by this Clob object. The substring + * begins at position pos and has up to length consecutive characters. * - * @param pos the first character of the substring to be - * extracted. The first character is at position 1. + * @param pos the first character of the substring to be extracted. The first character is at position 1. * @param length the number of consecutive characters to be copied - * @return a String that is the specified substring in the - * CLOB value designated by this Clob object - * @throws SQLException if there is an error accessing the - * CLOB value + * @return a String that is the specified substring in the CLOB value designated by this Clob object + * @throws SQLException if there is an error accessing the CLOB value */ @Override public String getSubString(long pos, int length) throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); try { - return buf.substring((int)(pos - 1), (int)(pos - 1 + length)); + return buffer.substring((int)(pos - 1), (int)(pos - 1 + length)); } catch (IndexOutOfBoundsException e) { throw new SQLException(e.getMessage()); } } /** - * Retrieves the number of characters in the CLOB value designated - * by this Clob object. + * Retrieves the number of characters in the CLOB value designated by this Clob object. * * @return length of the CLOB in characters - * @throws SQLException if there is an error accessing the length - * of the CLOB value + * @throws SQLException if there is an error accessing the length of the CLOB value */ @Override public long length() throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); - return (long)buf.length(); + return (long) buffer.length(); } /** - * Retrieves the character position at which the specified Clob - * object searchstr appears in this Clob object. The search - * begins at position start. + * Retrieves the character position at which the specified Clob object searchstr appears in this Clob object. + * The search begins at position start. * * @param searchstr the Clob object for which to search - * @param start the position at which to begin searching; - * the first position is 1 - * @return the position at which the Clob object appears or - * -1 if it is not present; the first position is 1 - * @throws SQLException if there is an error accessing the - * CLOB value + * @param start the position at which to begin searching; the first position is 1 + * @return the position at which the Clob object appears or -1 if it is not present; the first position is 1 + * @throws SQLException if there is an error accessing the CLOB value */ @Override public long position(Clob searchstr, long start) throws SQLException { @@ -150,50 +131,42 @@ public class MonetClob implements Clob { } /** - * Retrieves the character position at which the specified - * substring searchstr appears in the SQL CLOB value represented - * by this Clob object. The search begins at position start. + * Retrieves the character position at which the specified substring searchstr appears in the SQL CLOB value + * represented by this Clob object. The search begins at position start. * * @param searchstr the substring for which to search - * @param start the position at which to begin searching; - * the first position is 1 - * @return the position at which the substring appears or - * -1 if it is not present; the first position is 1 - * @throws SQLException if there is an error accessing the - * CLOB value + * @param start the position at which to begin searching; the first position is 1 + * @return the position at which the substring appears or -1 if it is not present; the first position is 1 + * @throws SQLException if there is an error accessing the CLOB value */ @Override public long position(String searchstr, long start) throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); - return (long)(buf.indexOf(searchstr, (int)(start - 1))); + return (long)(buffer.indexOf(searchstr, (int)(start - 1))); } @Override public OutputStream setAsciiStream(long pos) throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); throw new SQLException("Operation setAsciiStream(long pos) currently not supported", "0A000"); } @Override public Writer setCharacterStream(long pos) throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); throw new SQLException("Operation setCharacterStream(long pos) currently not supported", "0A000"); } /** - * Writes the given Java String to the CLOB value that this - * Clob object designates at the position pos. + * Writes the given Java String to the CLOB value that this Clob object designates at the position pos. * - * @param pos the position at which to start writing to the - * CLOB value that this Clob object represents - * @param str the string to be written to the CLOB value that - * this Clob designates + * @param pos the position at which to start writing to the CLOB value that this Clob object represents + * @param str the string to be written to the CLOB value that this Clob designates * @return the number of characters written - * @throws SQLException if there is an error accessing the - * CLOB value + * @throws SQLException if there is an error accessing the CLOB value */ @Override public int setString(long pos, String str) throws SQLException { @@ -201,32 +174,25 @@ public class MonetClob implements Clob { } /** - * Writes len characters of str, starting at character offset, - * to the CLOB value that this Clob represents. + * Writes len characters of str, starting at character offset, to the CLOB value that this Clob represents. * - * @param pos the position at which to start writing to this - * CLOB object - * @param str the string to be written to the CLOB value that - * this Clob object represents - * @param offset the offset into str to start reading the - * characters to be written + * @param pos the position at which to start writing to this CLOB object + * @param str the string to be written to the CLOB value that this Clob object represents + * @param offset the offset into str to start reading the characters to be written * @param len the number of characters to be written * @return the number of characters written - * @throws SQLException if there is an error accessing the - * CLOB value + * @throws SQLException if there is an error accessing the CLOB value */ @Override - public int setString(long pos, String str, int offset, int len) - throws SQLException - { - if (buf == null) + public int setString(long pos, String str, int offset, int len) throws SQLException { + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); - int buflen = buf.length(); + int buflen = buffer.length(); int retlen = Math.min(buflen, (int)(pos - 1 + len)); if (retlen > 0) { - buf.replace((int)(pos - 1), (int)(pos + retlen), str.substring(offset - 1, (offset + len))); + buffer.replace((int)(pos - 1), (int)(pos + retlen), str.substring(offset - 1, (offset + len))); return retlen; } else { return 0; @@ -234,32 +200,50 @@ public class MonetClob implements Clob { } /** - * Truncates the CLOB value that this Clob designates to - * have a length of len characters. + * Truncates the CLOB value that this Clob designates to have a length of len characters. * - * @param len the length, in bytes, to which the CLOB value - * should be truncated - * @throws SQLException if there is an error accessing the - * CLOB value + * @param len the length, in bytes, to which the CLOB value should be truncated + * @throws SQLException if there is an error accessing the CLOB value */ @Override public void truncate(long len) throws SQLException { - if (buf == null) + if (buffer.length() == 0) throw new SQLException("This Clob has been freed", "M1M20"); // this command is a no-op } /** - * Returns the String behind this Clob. This is a MonetClob - * extension that does not violate nor is described in the Clob - * interface. + * Returns the String behind this Clob. This is a MonetClob extension that does not violate nor is described in + * the Clob interface. * * @return the String this Clob wraps. */ @Override public String toString() { - if (buf == null) + if (buffer.length() == 0) return "<a freed MonetClob instance>"; - return buf.toString(); + return buffer.toString(); + } + + /** + * Overriding the equals method for the byte array. + */ + @Override + public boolean equals(Object obj) { + return obj instanceof MonetClob && this.toString().equals(obj.toString()); + } + + /** + * Overriding the hashCode method for the byte array. + */ + @Override + public int hashCode() { return this.buffer.toString().hashCode(); } + + /** + * Adding the compare to method. + */ + @Override + public int compareTo(MonetClob o) { + return this.toString().compareTo(o.toString()); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetConnection.java @@ -5,7 +5,7 @@ import nl.cwi.monetdb.jdbc.types.URL; import nl.cwi.monetdb.mcl.connection.MCLException; import nl.cwi.monetdb.mcl.connection.Debugger; import nl.cwi.monetdb.mcl.connection.MonetDBLanguage; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import nl.cwi.monetdb.mcl.responses.*; @@ -96,7 +96,7 @@ public abstract class MonetConnection ex protected boolean isDebugging; - protected Debugger ourSavior; + private Debugger ourSavior; protected AbstractProtocol<?> protocol; @@ -109,7 +109,8 @@ public abstract class MonetConnection ex * * @throws IOException if an error occurs */ - public MonetConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging) throws IOException { + public MonetConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, + boolean isDebugging) throws IOException { this.conn_props = props; this.database = database; this.hash = hash; @@ -139,10 +140,10 @@ public abstract class MonetConnection ex * list is empty; then there are no warnings. * @throws IOException if an I/O error occurs when creating the * socket - * @throws MCLParseException if bogus data is received + * @throws ProtocolException if bogus data is received * @throws MCLException if an MCL related error occurs */ - public abstract List<String> connect(String user, String pass) throws IOException, MCLParseException, MCLException; + public abstract List<String> connect(String user, String pass) throws IOException, ProtocolException, MCLException; public abstract int getBlockSize(); @@ -1594,7 +1595,7 @@ public abstract class MonetConnection ex try { switch (protocol.getNextStarterHeader()) { case Q_PARSE: - throw new MCLParseException("Q_PARSE header not allowed here", 1); + throw new ProtocolException("Q_PARSE header not allowed here", 1); case Q_TABLE: case Q_PREPARE: { res = protocol.getNextResultSetResponse(MonetConnection.this, @@ -1621,7 +1622,8 @@ public abstract class MonetConnection ex boolean isAutoCommit = ((AutoCommitResponse)res).isAutocommit(); if (MonetConnection.this.getAutoCommit() && isAutoCommit) { - MonetConnection.this.addWarning("Server enabled auto commit mode while local state already was auto commit.", "01M11"); + MonetConnection.this.addWarning("Server enabled auto commit mode " + + "while local state already was auto commit.", "01M11"); } MonetConnection.this.autoCommit = isAutoCommit; break; @@ -1634,10 +1636,11 @@ public abstract class MonetConnection ex res = next; } break; } - } catch (MCLParseException e) { - error = "M0M10!error while parsing start of header:\n" + e.getMessage() + - " found: '" + protocol.getRemainingStringLine(0).charAt(e.getErrorOffset()) + "'" + - " in: \"" + protocol.getRemainingStringLine(0) + "\"" + " at pos: " + e.getErrorOffset(); + } catch (ProtocolException e) { + error = "M0M10!error while parsing start of header:\n" + e.getMessage() + " found: '" + + protocol.getRemainingStringLine(0).charAt(e.getErrorOffset()) + "'" + + " in: \"" + protocol.getRemainingStringLine(0) + "\"" + " at pos: " + + e.getErrorOffset(); // flush all the rest protocol.waitUntilPrompt(); nextResponse = protocol.getCurrentServerResponseHeader(); @@ -1658,7 +1661,7 @@ public abstract class MonetConnection ex try { protocol.fetchNextResponseData(); iter.addLine(protocol.getCurrentServerResponseHeader(), protocol.getCurrentData()); - } catch (MCLParseException ex) { + } catch (ProtocolException ex) { // right, some protocol violation, skip the rest of the result error = "M0M10!" + ex.getMessage(); protocol.waitUntilPrompt();
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDataSource.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDataSource.java @@ -42,24 +42,20 @@ public class MonetDataSource extends Mon // private String serverName; // private String role; - private final MonetDriver driver; /** - * Constructor of a MonetDataSource which uses default settings for a - * connection. You probably want to change this setting using the - * method setURL. + * Constructor of a MonetDataSource which uses default settings for a connection. You probably want to change this + * setting using the method setURL. */ public MonetDataSource() { description = "MonetDB database"; url = "jdbc:monetdb://localhost/"; - driver = new MonetDriver(); } /** - * Attempts to establish a connection with the data source that this - * DataSource object represents. + * Attempts to establish a connection with the data source that this DataSource object represents. * * @return a MonetConnection * @throws SQLException if connecting to the database fails @@ -70,8 +66,7 @@ public class MonetDataSource extends Mon } /** - * Attempts to establish a connection with the data source that this - * DataSource object represents. + * Attempts to establish a connection with the data source that this DataSource object represents. * * @param username the username to use * @param password the password to use @@ -86,13 +81,11 @@ public class MonetDataSource extends Mon Properties props = new Properties(); props.put("user", username); props.put("password", password); - return driver.connect(url, props); } /** - * Gets the maximum time in seconds that this data source can wait while - * attempting to connect to a database. + * Gets the maximum time in seconds that this data source can wait while attempting to connect to a database. * * @return login timeout default is 0 (infinite) */ @@ -102,8 +95,7 @@ public class MonetDataSource extends Mon } /** - * Sets the maximum time in seconds that this data source will wait while - * attempting to connect to a database. + * Sets the maximum time in seconds that this data source will wait while attempting to connect to a database. * * @param seconds the number of seconds to wait before aborting the connect */ @@ -123,8 +115,7 @@ public class MonetDataSource extends Mon } /** - * Sets the log writer for this DataSource object to the given - * java.io.PrintWriter object. + * Sets the log writer for this DataSource object to the given java.io.PrintWriter object. * * @param out a PrintWriter - ignored */ @@ -204,8 +195,7 @@ public class MonetDataSource extends Mon * may be the root Logger. * * @return the parent Logger for this data source - * @throws SQLFeatureNotSupportedException if the data source does - * not use java.util.logging + * @throws SQLFeatureNotSupportedException if the data source does not use java.util.logging */ @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException {
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetDriver.java @@ -53,8 +53,7 @@ final public class MonetDriver implement /** Minor version of this driver */ private static final int DRIVERMINOR = 1; /** Version suffix string */ - private static final String DRIVERVERSIONSUFFIX = - "@JDBC_VER_SUFFIX@ based on MCL v@MCL_MAJOR@.@MCL_MINOR@"; + private static final String DRIVERVERSIONSUFFIX = "@JDBC_VER_SUFFIX@ based on MCL v@MCL_MAJOR@.@MCL_MINOR@"; // We're not fully compliant, but what we support is compliant /** Whether this driver is JDBC compliant or not */ private static final boolean MONETJDBCCOMPLIANT = false; @@ -191,11 +190,9 @@ final public class MonetDriver implement * getPropertyInfo method. * * @param url the URL of the database to which to connect - * @param info a proposed list of tag/value pairs that will be sent on - * connect open - * @return an array of DriverPropertyInfo objects describing possible - * properties. This array may be an empty array if no properties - * are required. + * @param info a proposed list of tag/value pairs that will be sent on connect open + * @return an array of DriverPropertyInfo objects describing possible properties. This array may be an empty array + * if no properties are required. */ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { if (!acceptsURL(url)) @@ -281,14 +278,13 @@ final public class MonetDriver implement //== end methods of interface driver - /** A static Map containing the mapping between MonetDB types and Java SQL types */ /* use SELECT sqlname, * FROM sys.types order by 1, id; to view all MonetDB types */ /* see http://docs.oracle.com/javase/7/docs/api/java/sql/Types.html to view all supported java SQL types */ private static Map<String, Integer> typeMap = new HashMap<>(); static { // fill the typeMap once - // typeMap.put("any", Integer.valueOf(Types.???)); + // typeMap.put("any", Types.???); typeMap.put("bigint", Types.BIGINT); typeMap.put("blob", Types.BLOB); typeMap.put("boolean", Types.BOOLEAN); @@ -299,24 +295,24 @@ final public class MonetDriver implement typeMap.put("double", Types.DOUBLE); typeMap.put("geometry", Types.VARCHAR); typeMap.put("geometrya", Types.VARCHAR); - typeMap.put("hugeint", Types.NUMERIC); + typeMap.put("hugeint", Types.NUMERIC); //but we will convert to java.math.BigInteger typeMap.put("inet", Types.VARCHAR); typeMap.put("int", Types.INTEGER); typeMap.put("json", Types.VARCHAR); - // typeMap.put("mbr", Integer.valueOf(Types.???)); + // typeMap.put("mbr", Types.???); typeMap.put("month_interval", Types.INTEGER); - typeMap.put("oid", Types.BIGINT); - // typeMap.put("ptr", Integer.valueOf(Types.???)); + // typeMap.put("oid", Types.BIGINT); + // typeMap.put("ptr", Types.???); typeMap.put("real", Types.REAL); - typeMap.put("sec_interval", Types.DECIMAL); + typeMap.put("sec_interval", Types.BIGINT); typeMap.put("smallint", Types.SMALLINT); - // typeMap.put("table", Integer.valueOf(Types.???)); + // typeMap.put("table", Types.???); typeMap.put("time", Types.TIME); typeMap.put("timestamp", Types.TIMESTAMP); typeMap.put("timestamptz", Types.TIMESTAMP); -// new in Java 8: Types.TIMESTAMP_WITH_TIMEZONE (value 2014). Can't use it yet as we compile for java 7 + // new in Java 8: Types.TIMESTAMP_WITH_TIMEZONE (value 2014). Can't use it yet as we compile for java 7 typeMap.put("timetz", Types.TIME); -// new in Java 8: Types.TIME_WITH_TIMEZONE (value 2013). Can't use it yet as we compile for java 7 + // new in Java 8: Types.TIME_WITH_TIMEZONE (value 2013). Can't use it yet as we compile for java 7 typeMap.put("tinyint", Types.TINYINT); typeMap.put("url", Types.VARCHAR); typeMap.put("uuid", Types.VARCHAR); @@ -328,8 +324,7 @@ final public class MonetDriver implement * Returns the java.sql.Types equivalent of the given MonetDB type. * * @param type the type as used by MonetDB - * @return the mathing java.sql.Types constant or java.sql.Types.OTHER if - * nothing matched on the given string + * @return the matching java.sql.Types constant or java.sql.Types.OTHER if nothing matched on the given string */ public static int getJavaType(String type) { // match the currentColumns type on a java.sql.Types constant @@ -337,14 +332,12 @@ final public class MonetDriver implement if (tp != null) { return tp; } else { - // this should not be able to happen - // do not assert, since maybe future versions introduce - // new types + // this should not be able to happen do not assert, since maybe future versions introduce new types return Types.OTHER; } } - private static String TypeMapppingSQL = null; // cache to optimise getSQLTypeMap() + private static String TypeMapppingSQL = null; // cache to optimise getSQLTypeMap() /** * Returns a String usable in an SQL statement to map the server types @@ -352,8 +345,7 @@ final public class MonetDriver implement * The returned string will be a SQL CASE x statement where the x is * replaced with the given currentColumns name (or expression) string. * - * @param column a String representing the value that should be evaluated - * in the SQL CASE statement + * @param column a String representing the value that should be evaluated in the SQL CASE statement * @return a SQL CASE statement */ static String getSQLTypeMap(String column) { @@ -396,8 +388,7 @@ final public class MonetDriver implement * may be the root Logger. * * @return the parent Logger for this data source - * @throws SQLFeatureNotSupportedException if the data source does - * not use java.util.logging + * @throws SQLFeatureNotSupportedException if the data source does not use java.util.logging */ public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException("java.util.logging not in use", "0A000");
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetPreparedStatement.java @@ -424,13 +424,7 @@ public class MonetPreparedStatement exte case Types.REAL: case Types.FLOAT: case Types.DOUBLE: - return true; case Types.BIGINT: - String monettype = getColumnTypeName(column); - if (monettype != null) { - if ("oid".equals(monettype) || "ptr".equals(monettype)) - return false; - } return true; case Types.BIT: // we don't use type BIT, it's here for completeness case Types.BOOLEAN: @@ -978,7 +972,8 @@ public class MonetPreparedStatement exte // if precision is now greater than that of the db, throw an error: if (x.precision() > digits[i]) { - throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + " (" + digits[i] + "/" + scale[i] + ")", "22003"); + throw new SQLDataException("DECIMAL value exceeds allowed digits/scale: " + x.toPlainString() + + " (" + digits[i] + "/" + scale[i] + ")", "22003"); } // MonetDB doesn't like leading 0's, since it counts them as part of @@ -2183,7 +2178,6 @@ public class MonetPreparedStatement exte setNull(parameterIndex, -1); return; } - setValue(parameterIndex, "'" + x.replaceAll("\\\\", "\\\\\\\\").replaceAll("'", "\\\\'") + "'"); } @@ -2444,7 +2438,7 @@ public class MonetPreparedStatement exte * @param paramIdx the parameter index number * @return a new created SQLException object with SQLState M1M05 */ - private final static SQLException newSQLInvalidParameterIndexException(int paramIdx) { + private static SQLException newSQLInvalidParameterIndexException(int paramIdx) { return new SQLException("Invalid Parameter Index number: " + paramIdx, "M1M05"); } @@ -2456,7 +2450,7 @@ public class MonetPreparedStatement exte * @param name the method name * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 */ - private final static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { + private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.java @@ -10,7 +10,6 @@ package nl.cwi.monetdb.jdbc; import nl.cwi.monetdb.jdbc.types.INET; import nl.cwi.monetdb.jdbc.types.URL; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; import nl.cwi.monetdb.mcl.responses.ResultSetResponse; import java.io.ByteArrayInputStream; @@ -42,8 +41,6 @@ import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; -import java.text.ParsePosition; -import java.text.SimpleDateFormat; import java.util.*; /** @@ -115,8 +112,7 @@ public class MonetResultSet extends Mone this.header = header; this.type = header.getRSType(); this.concurrency = header.getRSConcur(); - /* if we have a header object, the fetchSize used for this result set - is the header's cacheSize */ + /* if we have a header object, the fetchSize used for this result set is the header's cacheSize */ this.fetchSize = header.getCacheSize(); // well there is only one supported concurrency, so we don't have to bother about that // throws SQLException on getters of Header, so we find out immediately if an error occurred for this query @@ -162,6 +158,7 @@ public class MonetResultSet extends Mone //== methods of interface ResultSet // Chapter 14.2.2 Sun JDBC 3.0 Specification + /** * Moves the cursor to the given row number in this ResultSet object. * @@ -176,22 +173,18 @@ public class MonetResultSet extends Mone * * An attempt to position the cursor beyond the first/last row in the result * set leaves the cursor before the first row or after the last row. - * Note: calling absolute(1) is the same as calling first(). Calling - * absolute(-1) is the same as calling last(). + * Note: calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as calling last(). * - * @param row the number of the row to which the cursor should move. A - * positive number indicates the row number counting from the - * beginning of the result set; a negative number indicates the row - * number counting from the end of the result set + * @param row the number of the row to which the cursor should move. A positive number indicates the row number + * counting from the beginning of the result set; a negative number indicates the row number counting from + * the end of the result set * @return true if the cursor is on the result set; false otherwise - * @throws SQLException if a database access error occurs, or the result set - * type is TYPE_FORWARD_ONLY + * @throws SQLException if a database access error occurs, or the result set type is TYPE_FORWARD_ONLY */ @Override public boolean absolute(int row) throws SQLException { - if (row != curRow + 1 && type == TYPE_FORWARD_ONLY) throw - new SQLException("(Absolute) positioning not allowed on forward " + - " only result sets!", "M1M05"); + if (row != curRow + 1 && type == TYPE_FORWARD_ONLY) + throw new SQLException("(Absolute) positioning not allowed on forward only result sets!", "M1M05"); if (header.isClosed()) throw new SQLException("ResultSet is closed!", "M1M20"); @@ -202,8 +195,11 @@ public class MonetResultSet extends Mone row = tupleCount + row + 1; } // now place the row not farther than just before or after the result - if (row < 0) row = 0; // before first - else if (row > tupleCount + 1) row = tupleCount + 1; // after last + if (row < 0) { + row = 0; // before first + } else if (row > tupleCount + 1) { + row = tupleCount + 1; // after last + } this.values = header.getLine(row - 1); // store it @@ -212,8 +208,8 @@ public class MonetResultSet extends Mone } /** - * Moves the cursor to the end of this ResultSet object, just after the last - * row. This method has no effect if the result set contains no rows. + * Moves the cursor to the end of this ResultSet object, just after the last row. This method has no effect if the + * result set contains no rows. * * @throws SQLException if a database access error occurs or the result set * type is TYPE_FORWARD_ONLY @@ -224,8 +220,8 @@ public class MonetResultSet extends Mone } /** - * Moves the cursor to the front of this ResultSet object, just before the - * first row. This method has no effect if the result set contains no rows. + * Moves the cursor to the front of this ResultSet object, just before the first row. This method has no effect + * if the result set contains no rows. * * @throws SQLException if a database access error occurs or the result set * type is TYPE_FORWARD_ONLY @@ -236,9 +232,8 @@ public class MonetResultSet extends Mone } /** - * Clears all warnings reported for this ResultSet object. After a call to - * this method, the method getWarnings returns null until a new warning is - * reported for this ResultSet object. + * Clears all warnings reported for this ResultSet object. After a call to this method, the method getWarnings + * returns null until a new warning is reported for this ResultSet object. */ @Override public void clearWarnings() { @@ -246,9 +241,8 @@ public class MonetResultSet extends Mone } /** - * Releases this ResultSet object's database (and JDBC) resources - * immediately instead of waiting for this to happen when it is - * automatically closed. + * Releases this ResultSet object's database (and JDBC) resources immediately instead of waiting for this to happen + * when it is automatically closed. */ @Override public void close() { @@ -261,10 +255,10 @@ public class MonetResultSet extends Mone } // Chapter 14.2.3 from Sun JDBC 3.0 specification + /** - * Maps the given ResultSet column name to its ResultSet column index. - * Column names supplied to getter methods are case insensitive. If a select - * list contains the same column more than once, the first instance of the + * Maps the given ResultSet column name to its ResultSet column index. Column names supplied to getter methods are + * case insensitive. If a select list contains the same column more than once, the first instance of the * column will be returned. * * @param columnName the name of the column @@ -291,10 +285,8 @@ public class MonetResultSet extends Mone /** * Moves the cursor to the first row in this ResultSet object. * - * @return true if the cursor is on a valid row; false if there are no rows - * in the result set - * @throws SQLException - if a database access error occurs or the result - * set type is TYPE_FORWARD_ONLY + * @return true if the cursor is on a valid row; false if there are no rows in the result set + * @throws SQLException - if a database access error occurs or the result set type is TYPE_FORWARD_ONLY */ @Override public boolean first() throws SQLException { @@ -325,6 +317,7 @@ public class MonetResultSet extends Mone public InputStream getUnicodeStream(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("getUnicodeStream"); } + @Override @Deprecated public InputStream getUnicodeStream(String columnName) throws SQLException { @@ -406,9 +399,8 @@ public class MonetResultSet extends Mone * object. * * @param columnIndex the first column is 1, the second is 2, ... - * @return a java.io.Reader object that contains the column value; - * if the value is SQL NULL, the value returned is null in - * the Java programming language. + * @return a java.io.Reader object that contains the column value; if the value is SQL NULL, the value returned + * is null in the Java programming language. * @throws SQLException if a database access error occurs */ @Override @@ -498,7 +490,7 @@ public class MonetResultSet extends Mone return null; } lastReadWasNull = false; - return new MonetBlob((byte[]) val); + return (MonetBlob) val; } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { @@ -541,7 +533,7 @@ public class MonetResultSet extends Mone return null; } lastReadWasNull = false; - return new MonetClob((String) val); + return (MonetClob) val; } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { @@ -735,7 +727,8 @@ public class MonetResultSet extends Mone case Types.NUMERIC: return getBigDecimal(columnIndex).compareTo(BigDecimal.ZERO) != 0; default: - throw new SQLException("Conversion from " + types[columnIndex - 1] + " to boolean type not supported", "M1M05"); + throw new SQLException("Conversion from " + types[columnIndex - 1] + + " to boolean type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); @@ -804,8 +797,7 @@ public class MonetResultSet extends Mone * bytes represent the raw values returned by the driver. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -821,6 +813,7 @@ public class MonetResultSet extends Mone // According to Table B-6, getBytes() only operates on BINARY types switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BLOB: + return ((MonetBlob) val).getBuffer(); case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: @@ -841,11 +834,6 @@ public class MonetResultSet extends Mone * ResultSet object as a byte array in the Java programming language. The * bytes represent the raw values returned by the driver. * - * NOTE: Since the mapi protocol is ASCII-based, this method only returns - * Java byte representations of Strings, which is nothing more than - * an encoding into a sequence of bytes using the platform's default - * charset. - * * @param columnName the SQL name of the column * @return the column value; if the value is SQL NULL, the value returned * is null @@ -1045,8 +1033,8 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a float in the Java programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a float in the Java + * programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL NULL, the value returned is 0 @@ -1058,8 +1046,8 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as an int in the Java programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as an int in the + * Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 @@ -1076,22 +1064,6 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; return (Integer) val; - } catch (NumberFormatException e) { - // The oid datatype values (as string) have a @0 suffix in the string value. - // To allow successful parsing and conversion to int, we need to remove the suffix first - if ("oid".equals(types[columnIndex - 1])) { - String str = (String) this.values[columnIndex - 1]; - int len = str.length(); - if (len > 2 && str.endsWith("@0")) { - str = str.substring(0, len-2); - try { - return Integer.parseInt(str); - } catch (NumberFormatException nfe) { - throw newSQLNumberFormatException(nfe); - } - } - } - throw newSQLNumberFormatException(e); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { @@ -1100,8 +1072,8 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as an int in the Java programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as an int in the + * Java programming language. * * @param columnName the SQL name of the column * @return the column value; if the value is SQL NULL, the value returned is 0 @@ -1113,8 +1085,8 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a long in the Java programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a long in the Java + * programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value; if the value is SQL NULL, the value returned is 0 @@ -1131,34 +1103,17 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; return (Long) val; - } catch (NumberFormatException e) { - // The oid datatype values (as string) have a @0 suffix in the string value. - // To allow succesful parsing and conversion to long, we need to remove the suffix first - if ("oid".equals(types[columnIndex - 1])) { - String str = (String) this.values[columnIndex - 1]; - int len = str.length(); - if (len > 2 && str.endsWith("@0")) { - str = str.substring(0, len-2); - try { - return Long.parseLong(str); - } catch (NumberFormatException nfe) { - throw newSQLNumberFormatException(nfe); - } - } - } - throw newSQLNumberFormatException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a long in the Java programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a long in the Java + * programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is 0 + * @return the column value; if the value is SQL NULL, the value returned is 0 * @throws SQLException if the ResultSet object does not contain columnName */ @Override @@ -1168,9 +1123,9 @@ public class MonetResultSet extends Mone /* helper for the anonymous class inside getMetaData */ private abstract class rsmdw extends MonetWrapper implements ResultSetMetaData {} + /** - * Retrieves the number, types and properties of this ResultSet object's - * columns. + * Retrieves the number, types and properties of this ResultSet object's columns. * * @return the description of this ResultSet object's columns */ @@ -1347,14 +1302,7 @@ public class MonetResultSet extends Mone case Types.REAL: case Types.FLOAT: case Types.DOUBLE: - return true; case Types.BIGINT: - String monettype = getColumnTypeName(column); - if (monettype != null && monettype.length() == 3) { - // data of type oid or ptr is not signed - if ("oid".equals(monettype) || "ptr".equals(monettype)) - return false; - } return true; case Types.BIT: // we don't use type BIT, it's here for completeness case Types.BOOLEAN: @@ -1562,8 +1510,7 @@ public class MonetResultSet extends Mone */ @Override public String getCatalogName(int column) throws SQLException { - return null; // MonetDB does NOT support catalogs - + return null; // MonetDB does NOT support catalogs } /** @@ -1629,7 +1576,7 @@ public class MonetResultSet extends Mone if (conn != null) { Map<String,Class<?>> map = conn.getTypeMap(); if (map != null && map.containsKey(MonetDBType)) { - type = (Class)map.get(MonetDBType); + type = map.get(MonetDBType); } } if (type == null) { @@ -1694,9 +1641,8 @@ public class MonetResultSet extends Mone * Retrieves the designated column's database-specific type name. * * @param column the first column is 1, the second is 2, ... - * @return type name used by the database. If the column type is a - * user-defined type, then a fully-qualified type name is - * returned. + * @return type name used by the database. If the column type is a user-defined type, then a + * fully-qualified type name is returned. * @throws SQLException if there is no such column */ @Override @@ -1761,6 +1707,10 @@ public class MonetResultSet extends Mone case Types.DECIMAL: case Types.NUMERIC: case Types.BOOLEAN: + case Types.CHAR: + case Types.LONGVARCHAR: // MonetDB doesn't use type LONGVARCHAR, it's here for completeness + case Types.CLOB: + case Types.BLOB: return val; case Types.VARCHAR: { // The MonetDB types: inet, json, url and uuid are all mapped to Types.VARCHAR in MonetDriver.typeMap @@ -1811,13 +1761,6 @@ public class MonetResultSet extends Mone } return val; } - case Types.CHAR: - case Types.LONGVARCHAR: // MonetDB doesn't use type LONGVARCHAR, it's here for completeness - return val; - case Types.CLOB: - return new MonetClob((String) val); - case Types.BLOB: - return new MonetBlob((String) val); case Types.DATE: return getDate(columnIndex); case Types.TIME: @@ -1918,7 +1861,7 @@ public class MonetResultSet extends Mone return getDouble(columnIndex); } else if (type == byte[].class) { return getBytes(columnIndex); - } else if (type == java.sql.Date.class) { + } else if (type == Date.class) { return getDate(columnIndex); } else if (type == Time.class) { return getTime(columnIndex); @@ -1933,7 +1876,8 @@ public class MonetResultSet extends Mone try { Constructor<? extends SQLData> ctor = ((Class)type).getConstructor(); x = ctor.newInstance(); - } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | SecurityException | IllegalAccessException nsme) { + } catch (NoSuchMethodException | InstantiationException | InvocationTargetException + | SecurityException | IllegalAccessException nsme) { throw new SQLException(nsme.getMessage(), "M0M27"); } final int colnum = columnIndex; @@ -2104,10 +2048,11 @@ public class MonetResultSet extends Mone */ @Override public <T> T getObject(int i, Class<T> type) throws SQLException { - if (type == null) + if (type == null) { throw new SQLException("type is null", "M1M05"); - - throw new SQLFeatureNotSupportedException("cannot return a Java generic type based on static types from getXXX methods", "0AM34"); + } + throw new SQLFeatureNotSupportedException("cannot return a Java generic type based on static " + + "types from getXXX methods", "0AM34"); } /** @@ -2174,7 +2119,7 @@ public class MonetResultSet extends Mone case Types.LONGVARBINARY: return byte[].class; case Types.DATE: - return java.sql.Date.class; + return Date.class; case Types.TIME: return Time.class; case Types.TIMESTAMP: @@ -2183,7 +2128,6 @@ public class MonetResultSet extends Mone return Clob.class; case Types.BLOB: return Blob.class; - // all the rest are currently not implemented and used default: return String.class; @@ -2200,8 +2144,7 @@ public class MonetResultSet extends Mone * built-in types specified in the JDBC specification. If the value is an * SQL NULL, the driver returns a Java null. * - * This method may also be used to read database-specific abstract data - * types. + * This method may also be used to read database-specific abstract data types. * * @param columnName the SQL name of the column * @return a java.lang.Object holding the column value @@ -2240,8 +2183,7 @@ public class MonetResultSet extends Mone } /** - * Retrieves the current row number. The first row is number 1, the second - * number 2, and so on. + * Retrieves the current row number. The first row is number 1, the second number 2, and so on. * * @return the current row number; 0 if there is no current row */ @@ -2256,11 +2198,9 @@ public class MonetResultSet extends Mone * programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if there is no such column - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public RowId getRowId(int columnIndex) throws SQLException { @@ -2273,11 +2213,9 @@ public class MonetResultSet extends Mone * programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if the ResultSet object does not contain columnName - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public RowId getRowId(String columnName) throws SQLException { @@ -2289,8 +2227,7 @@ public class MonetResultSet extends Mone * ResultSet object as a short in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is 0 + * @return the column value; if the value is SQL NULL, the value returned is 0 * @throws SQLException if there is no such column */ @Override @@ -2303,8 +2240,8 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; return (Short) val; - } catch (NumberFormatException e) { - throw newSQLNumberFormatException(e); + } catch (ClassCastException ex) { + throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } @@ -2315,8 +2252,7 @@ public class MonetResultSet extends Mone * ResultSet object as a short in the Java programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is 0 + * @return the column value; if the value is SQL NULL, the value returned is 0 * @throws SQLException if the ResultSet object does not contain columnName */ @Override @@ -2342,8 +2278,7 @@ public class MonetResultSet extends Mone * ResultSet object as a String in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if there is no such column */ @Override @@ -2356,6 +2291,8 @@ public class MonetResultSet extends Mone } lastReadWasNull = false; return val; + } catch (ClassCastException ex) { + throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } @@ -2366,8 +2303,7 @@ public class MonetResultSet extends Mone * ResultSet object as a String in the Java programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if the ResultSet object does not contain columnName */ @Override @@ -2382,11 +2318,9 @@ public class MonetResultSet extends Mone * and LONGNVARCHAR columns. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if there is no such column - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public String getNString(int columnIndex) throws SQLException { @@ -2400,11 +2334,9 @@ public class MonetResultSet extends Mone * and LONGNVARCHAR columns. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if the ResultSet object does not contain columnName - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public String getNString(String columnName) throws SQLException { @@ -2412,15 +2344,13 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row - * of this ResultSet as a java.sql.SQLXML object in the Java - * programming language. + * Retrieves the value of the designated column in the current row of this ResultSet as a java.sql.SQLXML object + * in the Java programming language. * * @param i the first column is 1, the second is 2, ... * @return a SQLXML object that maps an SQL XML value * @throws SQLException if a database access error occurs - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public SQLXML getSQLXML(int i) throws SQLException { @@ -2428,180 +2358,27 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row - * of this ResultSet as a java.sql.SQLXML object in the Java - * programming language. + * Retrieves the value of the designated column in the current row of this ResultSet as a java.sql.SQLXML object + * in the Java programming language. * - * @param colName the label for the column specified with the SQL AS - * clause. If the SQL AS clause was not specified, then the - * label is the name of the column + * @param colName the label for the column specified with the SQL AS clause. If the SQL AS clause was not specified, + * then the label is the name of the column * @return a SQLXML object that maps an SQL XML value * @throws SQLException if a database access error occurs - * @throws SQLFeatureNotSupportedException the JDBC driver does - * not support this method + * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public SQLXML getSQLXML(String colName) throws SQLException { throw newSQLFeatureNotSupportedException("getSQLXML"); } - // This behaviour is according table B-6 of Sun JDBC Specification 3.0 - private SimpleDateFormat ts = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - private SimpleDateFormat t = new SimpleDateFormat("HH:mm:ss"); - private SimpleDateFormat d = new SimpleDateFormat("yyyy-MM-dd"); - /** - * Helper method which parses the date/time value for columns of type - * TIME, DATE and TIMESTAMP. For the types CHAR, VARCHAR and - * LONGVARCHAR an attempt is made to parse the date according to the - * given type. The given Calender object is filled with the parsed - * data. Optional fractional seconds (nanos) are returned by this - * method. If the underlying type of the column is none of the - * mentioned six, January 1st 1970 0:00:00 GMT is returned.<br /> - * The dates are parsed with the given Calendar. - * - * @param cal the Calendar to use/fill when parsing the date/time - * @param columnIndex the column to parse - * @param type the corresponding java.sql.Types type of the calling - * function - * @return the fractional seconds (nanos) or -1 if the value is NULL - * @throws SQLException if a database error occurs - */ - private int getJavaDate(Calendar cal, int columnIndex, int type) throws SQLException { //TODO check this :( - if (cal == null) - throw new IllegalArgumentException("No Calendar object given!"); - - final String monetDate; - final String MonetDBType; - int JdbcType; - try { - monetDate = (String) this.values[columnIndex - 1]; - if (monetDate == null) { - lastReadWasNull = true; - return -1; - } - lastReadWasNull = false; - MonetDBType = types[columnIndex - 1]; - JdbcType = JdbcSQLTypes[columnIndex - 1]; - // If we got a string type, set the JdbcType to the given type - // so we attempt to parse it as the caller thinks it is. - if (JdbcType == Types.CHAR || JdbcType == Types.VARCHAR || JdbcType == Types.LONGVARCHAR || JdbcType == Types.CLOB) { - JdbcType = type; - } - } catch (IndexOutOfBoundsException e) { - throw newSQLInvalidColumnIndexException(columnIndex); - } - - TimeZone ptz = cal.getTimeZone(); - - // it is important to parse the time in the given timezone in - // order to get a correct (UTC) time value, hence we need to - // parse it first - if (MonetDBType != null && ("timetz".equals(MonetDBType) || "timestamptz".equals(MonetDBType))) { - int vallen = monetDate.length(); - if (vallen >= 6) { - // MonetDB/SQL99: Sign TwoDigitHours : Minutes - ptz = TimeZone.getTimeZone("GMT" + monetDate.substring(vallen - 6, vallen)); - } - } - - java.util.Date pdate; - ParsePosition ppos = new ParsePosition(0); - switch(JdbcType) { - case Types.DATE: - d.setTimeZone(ptz); - pdate = d.parse(monetDate, ppos); - break; - case Types.TIME: - t.setTimeZone(ptz); - pdate = t.parse(monetDate, ppos); - break; - case Types.TIMESTAMP: - ts.setTimeZone(ptz); - pdate = ts.parse(monetDate, ppos); - break; - default: - addWarning("unsupported data type", "01M03"); - cal.clear(); - return 0; - } - if (pdate == null) { - // parsing failed - int epos = ppos.getErrorIndex(); - if (epos == -1) { - addWarning("parsing '" + monetDate + "' failed", "01M10"); - } else if (epos < monetDate.length()) { - addWarning("parsing failed, found: '" + monetDate.charAt(epos) + "' in: \"" + monetDate + "\"" + - " at pos: " + ppos.getErrorIndex(), "01M10"); - } else { - addWarning("parsing failed, expected more data after '" + monetDate + "'", "01M10"); - } - // default value - cal.clear(); - return 0; - } - cal.setTime(pdate); - - int nanos = 0; - if (JdbcType == Types.TIME || JdbcType == Types.TIMESTAMP) { - // parse additional nanos (if any) - int pos = ppos.getIndex(); - char[] monDate = monetDate.toCharArray(); - if (pos < monDate.length && monDate[pos] == '.') { - pos++; - int ctr; - try { - nanos = getIntrinsicValue(monDate[pos], pos++); - for (ctr = 1; pos < monDate.length && monDate[pos] >= '0' && monDate[pos] <= '9'; ctr++) { - if (ctr < 9) { - nanos *= 10; - nanos += getIntrinsicValue(monDate[pos], pos); - } - if (ctr == 2) // we have three at this point - cal.set(Calendar.MILLISECOND, nanos); - pos++; - } - while (ctr++ < 9) - nanos *= 10; - } catch(MCLParseException e) { - addWarning(e.getMessage() + " found: '" + monDate[e.getErrorOffset()] + "'" + - " in: \"" + monetDate + "\" at pos: " + e.getErrorOffset(), "01M10"); - // default value - cal.clear(); - nanos = 0; - } - } - } - return nanos; - } - - /** - * Small helper method that returns the intrinsic value of a char if - * it represents a digit. If a non-digit character is encountered - * an MCLParseException is thrown. - * - * @param c the char - * @param pos the position - * @return the intrinsic value of the char - * @throws MCLParseException if c is not a digit - */ - private final static int getIntrinsicValue(char c, int pos) throws MCLParseException { - // note: don't use Character.isDigit() here, because - // we only want ISO-LATIN-1 digits - if (c >= '0' && c <= '9') { - return (int)c - (int)'0'; - } else { - throw new MCLParseException("Expected a digit", pos); - } - } - /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a java.sql.Date object in the Java programming * language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs * @see #getDate(int col, Calendar cal) */ @@ -2619,14 +2396,24 @@ public class MonetResultSet extends Mone * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the java.util.Calendar object to use in constructing the date - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override public Date getDate(int columnIndex, Calendar cal) throws SQLException { - int ret = getJavaDate(cal, columnIndex, Types.DATE); - return ret == -1 ? null : new java.sql.Date(cal.getTimeInMillis()); + try { + Date val = (Date) this.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + return val; + } catch (ClassCastException ex) { + throw new SQLException(ex.getMessage()); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } } /** @@ -2634,10 +2421,8 @@ public class MonetResultSet extends Mone * ResultSet object as a java.sql.Date object in the Java programming * language. * - * @param columnName the SQL name of the column from which to retrieve the - * value - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @param columnName the SQL name of the column from which to retrieve the value + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2652,11 +2437,9 @@ public class MonetResultSet extends Mone * millisecond value for the date if the underlying database does not store * timezone information. * - * @param columnName the SQL name of the column from which to retrieve the - * value + * @param columnName the SQL name of the column from which to retrieve the value * @param cal the java.util.Calendar object to use in constructing the date - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2665,13 +2448,11 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a java.sql.Time object in the Java programming - * language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Time + * object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2687,27 +2468,36 @@ public class MonetResultSet extends Mone * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... - * @param cal the java.util.Calendar object to use in constructing the - * timestamp - * @return the column value as a java.sql.Timestamp object; if the value is - * SQL NULL, the value returned is null in the Java programming - * language + * @param cal the java.util.Calendar object to use in constructing the timestamp + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null in + * the Java programming language * @throws SQLException if a database access error occurs */ @Override public Time getTime(int columnIndex, Calendar cal) throws SQLException { - int ret = getJavaDate(cal, columnIndex, Types.TIME); - return ret == -1 ? null : new Time(cal.getTimeInMillis()); + if (cal == null) + throw new IllegalArgumentException("No Calendar object given!"); + try { + Time val = (Time) this.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + return val; + } catch (ClassCastException ex) { + throw new SQLException(ex.getMessage()); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a java.sql.Time object in the Java programming - * language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Time + * object in the Java programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2723,11 +2513,9 @@ public class MonetResultSet extends Mone * timezone information. * * @param columnName the SQL name of the column - * @param cal the java.util.Calendar object to use in constructing the - * timestamp - * @return the column value as a java.sql.Timestamp object; if the value is - * SQL NULL, the value returned is null in the Java programming - * language + * @param cal the java.util.Calendar object to use in constructing the timestamp + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null + * in the Java programming language * @throws SQLException if a database access error occurs */ @Override @@ -2736,13 +2524,11 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a java.sql.Timestamp object in the Java programming - * language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp + * object in the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2758,32 +2544,36 @@ public class MonetResultSet extends Mone * store timezone information. * * @param columnIndex the first column is 1, the second is 2, ... - * @param cal the java.util.Calendar object to use in constructing the - * timestamp - * @return the column value as a java.sql.Timestamp object; if the value is - * SQL NULL, the value returned is null in the Java programming - * language + * @param cal the java.util.Calendar object to use in constructing the timestamp + * @return the column value as a java.sql.Timestamp object; if the value is SQL NULL, the value returned is null + * in the Java programming language * @throws SQLException if a database access error occurs */ @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - int nanos = getJavaDate(cal, columnIndex, Types.TIMESTAMP); - if (nanos == -1) - return null; - - Timestamp ts = new Timestamp(cal.getTimeInMillis()); - ts.setNanos(nanos); - return ts; + if (cal == null) + throw new IllegalArgumentException("No Calendar object given!"); + try { + Timestamp val = (Timestamp) this.values[columnIndex - 1]; + if (val == null) { + lastReadWasNull = true; + return null; + } + lastReadWasNull = false; + return val; + } catch (ClassCastException ex) { + throw new SQLException(ex.getMessage()); + } catch (IndexOutOfBoundsException e) { + throw newSQLInvalidColumnIndexException(columnIndex); + } } /** - * Retrieves the value of the designated column in the current row of this - * ResultSet object as a java.sql.Timestamp object in the Java programming - * language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.Timestamp + * object in the Java programming language. * * @param columnName the SQL name of the column - * @return the column value; if the value is SQL NULL, the value returned - * is null + * @return the column value; if the value is SQL NULL, the value returned is null * @throws SQLException if a database access error occurs */ @Override @@ -2799,11 +2589,9 @@ public class MonetResultSet extends Mone * store timezone information. * * @param columnName the SQL name of the column - * @param cal the java.util.Calendar object to use in constructing the - * timestamp + * @param cal the java.util.Calendar object to use in constructing the timestamp * @return the column value as a java.sql.Timestamp object; if the value is - * SQL NULL, the value returned is null in the Java programming - * language + * SQL NULL, the value returned is null in the Java programming language * @throws SQLException if a database access error occurs */ @Override @@ -2824,17 +2612,13 @@ public class MonetResultSet extends Mone } /** - * Retrieves the value of the designated column in the current row - * of this ResultSet object as a java.net.URL object in the Java - * programming language. + * Retrieves the value of the designated column in the current row of this ResultSet object as a java.net.URL + * object in the Java programming language. * - * @param columnIndex the index of the column 1 is the first, - * 2 is the second,... - * @return the column value as a java.net.URL object; if the value - * is SQL NULL, the value returned is null in the Java - * programming language - * @throws SQLException if a database access error occurs, or if a - * URL is malformed + * @param columnIndex the index of the column 1 is the first, 2 is the second,... + * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null in the + * Java programming language + * @throws SQLException if a database access error occurs, or if a URL is malformed */ @Override public java.net.URL getURL(int columnIndex) throws SQLException { @@ -2861,11 +2645,9 @@ public class MonetResultSet extends Mone * programming language. * * @param columnName the SQL name of the column - * @return the column value as a java.net.URL object; if the value - * is SQL NULL, the value returned is null in the Java - * programming language - * @throws SQLException if a database access error occurs, or if a - * URL is malformed + * @return the column value as a java.net.URL object; if the value is SQL NULL, the value returned is null in the + * Java programming language + * @throws SQLException if a database access error occurs, or if a URL is malformed */ @Override public java.net.URL getURL(String columnName) throws SQLException { @@ -2898,8 +2680,7 @@ public class MonetResultSet extends Mone } /** - * Retrieves whether the cursor is after the last row in this ResultSet - * object. + * Retrieves whether the cursor is after the last row in this ResultSet object. * * @return true if the cursor is after the last row; false if the cursor is * at any other position or the result set contains no rows @@ -2910,8 +2691,7 @@ public class MonetResultSet extends Mone } /** - * Retrieves whether the cursor is before the first row in this ResultSet - * object. + * Retrieves whether the cursor is before the first row in this ResultSet object. * * @return true if the cursor is before the first row; false if the cursor * is at any other position or the result set contains no rows @@ -2922,12 +2702,10 @@ public class MonetResultSet extends Mone } /** - * Retrieves whether this ResultSet object has been closed. A - * ResultSet is closed if the method close has been called on it, or - * if it is automatically closed. + * Retrieves whether this ResultSet object has been closed. A ResultSet is closed if the method close has been + * called on it, or if it is automatically closed. * - * @return true if this ResultSet object is closed; false if it is - * still open + * @return true if this ResultSet object is closed; false if it is still open */ @Override public boolean isClosed() { @@ -2935,8 +2713,7 @@ public class MonetResultSet extends Mone } /** - * Retrieves whether the cursor is on the first row of this ResultSet - * object. + * Retrieves whether the cursor is on the first row of this ResultSet object. * * @return true if the cursor is on the first row; false otherwise */ @@ -2958,10 +2735,8 @@ public class MonetResultSet extends Mone /** * Moves the cursor to the last row in this ResultSet object. * - * @return true if the cursor is on a valid row; false if there are no rows - * in the result set - * @throws SQLException if a database access error occurs or the result set - * type is TYPE_FORWARD_ONLY + * @return true if the cursor is on a valid row; false if there are no rows in the result set + * @throws SQLException if a database access error occurs or the result set type is TYPE_FORWARD_ONLY */ @Override public boolean last() throws SQLException { @@ -2978,10 +2753,8 @@ public class MonetResultSet extends Mone * next will implicitly close it. A ResultSet object's warning chain is * cleared when a new row is read. * - * @return true if the new current row is valid; false if there are no - * more rows - * @throws SQLException if a database access error occurs or ResultSet is - * closed + * @return true if the new current row is valid; false if there are no more rows + * @throws SQLException if a database access error occurs or ResultSet is closed */ @Override public boolean next() throws SQLException { @@ -2991,10 +2764,9 @@ public class MonetResultSet extends Mone /** * Moves the cursor to the previous row in this ResultSet object. * - * @return true if the cursor is on a valid row; false if it is off - * the result set - * @throws SQLException if a database access error occurs or ResultSet is - * closed or the result set type is TYPE_FORWARD_ONLY + * @return true if the cursor is on a valid row; false if it is off the result set + * @throws SQLException if a database access error occurs or ResultSet is closed or the result set type is + * TYPE_FORWARD_ONLY */ @Override public boolean previous() throws SQLException { @@ -3081,8 +2853,7 @@ public class MonetResultSet extends Mone return false; } - /* the next methods are all related to updateable result sets, which we - currently do not support */ + /* the next methods are all related to updateable result sets, which we currently do not support */ @Override public void cancelRowUpdates() throws SQLException { throw newSQLFeatureNotSupportedException("cancelRowUpdates"); @@ -3113,7 +2884,6 @@ public class MonetResultSet extends Mone throw newSQLFeatureNotSupportedException("refreshRow"); } - @Override public void updateArray(int columnIndex, Array x) throws SQLException { throw newSQLFeatureNotSupportedException("updateArray"); @@ -3289,10 +3059,6 @@ public class MonetResultSet extends Mone throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } - public void updateNCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - throw newSQLFeatureNotSupportedException("updateNCharacterStream"); - } - @Override public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); @@ -3303,10 +3069,6 @@ public class MonetResultSet extends Mone throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } - public void updateNCharacterStream(String columnName, Reader reader, int length) throws SQLException { - throw newSQLFeatureNotSupportedException("updateNCharacterStream"); - } - @Override public void updateNCharacterStream(String columnName, Reader reader, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); @@ -3544,8 +3306,7 @@ public class MonetResultSet extends Mone * its value and then call the method wasNull to see if the value read was * SQL NULL. * - * @return true if the last column value read was SQL NULL and false - * otherwise + * @return true if the last column value read was SQL NULL and false otherwise */ @Override public boolean wasNull() { @@ -3577,22 +3338,11 @@ public class MonetResultSet extends Mone * @param colIdx the column index number * @return a new created SQLException object with SQLState M1M05 */ - public final static SQLException newSQLInvalidColumnIndexException(int colIdx) { + static SQLException newSQLInvalidColumnIndexException(int colIdx) { return new SQLException("Invalid Column Index number: " + colIdx, "M1M05"); } /** - * Small helper method that formats the "Could not convert value to a number" message - * and creates a new SQLException object whose SQLState is set to "22003": Numeric value out of range. - * - * @param error the NumberFormatException - * @return a new created SQLException object with SQLState 22003 - */ - private final static SQLException newSQLNumberFormatException(NumberFormatException error) { - return new SQLException("Could not convert value to a number. " + error.getMessage(), "22003"); - } - - /** * Small helper method that formats the "Method ... not implemented" message * and creates a new SQLFeatureNotSupportedException object * whose SQLState is set to "0A000". @@ -3600,7 +3350,7 @@ public class MonetResultSet extends Mone * @param name the method name * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 */ - private final static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { + private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/MonetStatement.java @@ -47,7 +47,7 @@ import java.util.concurrent.locks.Reentr */ public class MonetStatement extends MonetWrapper implements Statement { /** the default value of maxRows, 0 indicates unlimited */ - static final int DEF_MAXROWS = 0; + private static final int DEF_MAXROWS = 0; /** The parental Connection object */ private MonetConnection connection; @@ -60,7 +60,7 @@ public class MonetStatement extends Mone /** Whether this Statement object is closed or not */ protected boolean closed; /** Whether the application wants this Statement object to be pooled */ - private boolean poolable; + boolean poolable; /** Whether this Statement should be closed if the last ResultSet closes */ private boolean closeOnCompletion = false; /** The size of the blocks of results to ask for at the server */ @@ -823,7 +823,8 @@ public class MonetStatement extends Mone */ @Override public ResultSet getResultSet() throws SQLException { - return (header instanceof ResultSetResponse) ? new MonetResultSet(this, (ResultSetResponse)header) : null; + return (header instanceof ResultSetResponse) ? new MonetResultSet(this, (ResultSetResponse)header) + : null; } /** @@ -880,7 +881,6 @@ public class MonetStatement extends Mone } else if (header instanceof SchemaResponse) { ret = ((SchemaResponse)header).getState(); } - return ret; } @@ -958,7 +958,8 @@ public class MonetStatement extends Mone @Override public void setEscapeProcessing(boolean enable) throws SQLException { if (enable) { - addWarning("setEscapeProcessing: JDBC escape syntax is not supported by this driver", "01M22"); + addWarning("setEscapeProcessing: JDBC escape syntax is not supported by this driver", + "01M22"); } } @@ -978,7 +979,8 @@ public class MonetStatement extends Mone */ @Override public void setFetchDirection(int direction) throws SQLException { - if (direction == ResultSet.FETCH_FORWARD || direction == ResultSet.FETCH_REVERSE || direction == ResultSet.FETCH_UNKNOWN) { + if (direction == ResultSet.FETCH_FORWARD || direction == ResultSet.FETCH_REVERSE + || direction == ResultSet.FETCH_UNKNOWN) { fetchDirection = direction; } else { throw new SQLException("Illegal direction: " + direction, "M1M05");
--- a/src/main/java/nl/cwi/monetdb/jdbc/types/INET.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/types/INET.java @@ -36,8 +36,7 @@ public class INET implements SQLData { @Override public void readSQL(SQLInput stream, String typeName) throws SQLException { if (typeName.compareTo("inet") != 0) - throw new SQLException("can only use this class with 'inet' type", - "M1M05"); + throw new SQLException("can only use this class with 'inet' type", "M1M05"); inet = stream.readString(); } @@ -53,7 +52,7 @@ public class INET implements SQLData { public void fromString(String newinet) throws Exception { if (newinet == null) { - inet = newinet; + inet = null; return; } int slash = newinet.indexOf('/'); @@ -64,8 +63,7 @@ public class INET implements SQLData { try { netmask = Integer.parseInt(newinet.substring(slash + 1)); } catch (NumberFormatException nfe) { - throw new Exception("cannot parse netmask bits: " + - newinet.substring(slash + 1)); + throw new Exception("cannot parse netmask bits: " + newinet.substring(slash + 1)); } if (netmask <= 0 || netmask > 32) throw new Exception("netmask must be >0 and <32"); @@ -83,8 +81,7 @@ public class INET implements SQLData { throw new Exception("cannot parse number: " + quads[i]); } if (quadv < 0 || quadv > 255) - throw new Exception("value must be between 0 and 255: " + - quads[i]); + throw new Exception("value must be between 0 and 255: " + quads[i]); } // everything is fine inet = newinet; @@ -103,12 +100,11 @@ public class INET implements SQLData { public void setAddress(String newinet) throws Exception { if (newinet == null) { - inet = newinet; + inet = null; return; } if (newinet.indexOf('/') != -1) - throw new Exception("IPv4 address cannot contain '/' " + - "(use fromString() instead)"); + throw new Exception("IPv4 address cannot contain '/' (use fromString() instead)"); fromString(newinet); } @@ -123,8 +119,7 @@ public class INET implements SQLData { try { return Integer.parseInt(inet.substring(slash + 1)); } catch (NumberFormatException nfe) { - throw new SQLException("cannot parse netmask bits: " + - inet.substring(slash + 1), "M0M27"); + throw new SQLException("cannot parse netmask bits: " + inet.substring(slash + 1), "M0M27"); } }
--- a/src/main/java/nl/cwi/monetdb/jdbc/types/URL.java +++ b/src/main/java/nl/cwi/monetdb/jdbc/types/URL.java @@ -27,8 +27,7 @@ public class URL implements SQLData { @Override public void readSQL(SQLInput stream, String typeName) throws SQLException { if (typeName.compareTo("url") != 0) - throw new SQLException("can only use this class with 'url' type", - "M1M05"); + throw new SQLException("can only use this class with 'url' type", "M1M05"); url = stream.readString(); } @@ -44,7 +43,7 @@ public class URL implements SQLData { public void fromString(String newurl) throws Exception { if (newurl == null) { - url = newurl; + url = null; return; } new java.net.URL(newurl);
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/EmbeddedConnection.java @@ -4,7 +4,7 @@ import nl.cwi.monetdb.embedded.env.Monet import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedDatabase; import nl.cwi.monetdb.embedded.env.MonetDBEmbeddedException; import nl.cwi.monetdb.jdbc.MonetConnection; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.embedded.EmbeddedProtocol; import java.io.*; @@ -18,7 +18,8 @@ public final class EmbeddedConnection ex private final String directory; - public EmbeddedConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String directory) throws IOException { + EmbeddedConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, + boolean isDebugging, String directory) throws IOException { super(props, database, hash, language, blobIsBinary, isDebugging); this.directory = directory; } @@ -32,9 +33,10 @@ public final class EmbeddedConnection ex } @Override - public List<String> connect(String user, String pass) throws IOException, MCLParseException, MCLException { + public List<String> connect(String user, String pass) throws IOException, ProtocolException, MCLException { try { - if(MonetDBEmbeddedDatabase.IsDatabaseRunning() && !MonetDBEmbeddedDatabase.GetDatabaseDirectory().equals(this.directory)) { + if(MonetDBEmbeddedDatabase.IsDatabaseRunning() && + !MonetDBEmbeddedDatabase.GetDatabaseDirectory().equals(this.directory)) { throw new MCLException("The embedded database is already running on a different directory!"); } else { MonetDBEmbeddedDatabase.StartDatabase(this.directory, true, false); @@ -69,10 +71,6 @@ public final class EmbeddedConnection ex @Override public void closeUnderlyingConnection() throws IOException { - try { - MonetDBEmbeddedDatabase.StopDatabase(); - } catch (MonetDBEmbeddedException e) { - // ignore it - } + ((EmbeddedProtocol)protocol).getEmbeddedConnection().closeConnection(); } }
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MCLException.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MCLException.java @@ -16,11 +16,11 @@ public class MCLException extends Except private static final long serialVersionUID = 1L; - public MCLException(String e) { + MCLException(String e) { super(e); } - public MCLException(Throwable t) { + MCLException(Throwable t) { super(t); } }
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MapiConnection.java @@ -1,10 +1,8 @@ package nl.cwi.monetdb.mcl.connection; import nl.cwi.monetdb.jdbc.MonetConnection; -import nl.cwi.monetdb.mcl.io.BufferedMCLReader; -import nl.cwi.monetdb.mcl.io.BufferedMCLWriter; import nl.cwi.monetdb.mcl.io.SocketConnection; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import nl.cwi.monetdb.mcl.protocol.oldmapi.OldMapiProtocol; @@ -67,17 +65,18 @@ import java.util.*; public class MapiConnection extends MonetConnection { /** The hostname to connect to */ - protected final String hostname; + private final String hostname; /** The port to connect on the host to */ - protected final int port; + private final int port; /** Whether we should follow redirects */ - protected boolean followRedirects = true; + private boolean followRedirects = true; /** How many redirections do we follow until we're fed up with it? */ - protected int ttl = 10; + private int ttl = 10; /** protocol version of the connection */ - protected int version; + private int version; - public MapiConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, boolean isDebugging, String hostname, int port) throws IOException { + MapiConnection(Properties props, String database, String hash, String language, boolean blobIsBinary, + boolean isDebugging, String hostname, int port) throws IOException { super(props, database, hash, language, blobIsBinary, isDebugging); this.hostname = hostname; this.port = port; @@ -184,7 +183,7 @@ public class MapiConnection extends Mone } @Override - public List<String> connect(String user, String pass) throws IOException, MCLParseException, MCLException { + public List<String> connect(String user, String pass) throws IOException, ProtocolException, MCLException { // Wrap around the internal connect that needs to know if it // should really make a TCP connection or not. List<String> res = connect(this.hostname, this.port, user, pass, true); @@ -194,7 +193,8 @@ public class MapiConnection extends Mone return res; } - private List<String> connect(String host, int port, String user, String pass, boolean makeConnection) throws IOException, MCLParseException, MCLException { + private List<String> connect(String host, int port, String user, String pass, boolean makeConnection) + throws IOException, ProtocolException, MCLException { if (ttl-- <= 0) throw new MCLException("Maximum number of redirects reached, aborting connection attempt. Sorry."); @@ -216,7 +216,8 @@ public class MapiConnection extends Mone pro.waitUntilPrompt(); String firstLine = pro.getRemainingStringLine(0); - String test = this.getChallengeResponse(firstLine, user, pass, this.language.getRepresentation(), this.database, this.hash); + String test = this.getChallengeResponse(firstLine, user, pass, this.language.getRepresentation(), + this.database, this.hash); pro.writeNextCommand(MonetDBLanguage.EmptyString, test.getBytes(), MonetDBLanguage.EmptyString); List<String> redirects = new ArrayList<>(); @@ -261,7 +262,7 @@ public class MapiConnection extends Mone try { u = new URI(suri.substring(5)); } catch (URISyntaxException e) { - throw new MCLParseException(e.toString()); + throw new ProtocolException(e.toString()); } String tmp = u.getQuery(); @@ -360,15 +361,17 @@ public class MapiConnection extends Mone * @param hash the hash method(s) to use, or NULL for all supported * hashes */ - private String getChallengeResponse(String chalstr, String username, String password, String language, String database, String hash) - throws MCLParseException, MCLException, IOException { + private String getChallengeResponse(String chalstr, String username, String password, String language, + String database, String hash) + throws ProtocolException, MCLException, IOException { String response; String algo; // parse the challenge string, split it on ':' String[] chaltok = chalstr.split(":"); - if (chaltok.length <= 4) throw - new MCLParseException("Server challenge string unusable! Challenge contains too few tokens: " + chalstr); + if (chaltok.length <= 4) + throw new ProtocolException("Server challenge string unusable! Challenge contains too few tokens: " + + chalstr); // challenge string to use as salt/key String challenge = chaltok[0]; @@ -376,7 +379,7 @@ public class MapiConnection extends Mone try { version = Integer.parseInt(chaltok[2].trim()); // protocol version } catch (NumberFormatException e) { - throw new MCLParseException("Protocol version unparseable: " + chaltok[3]); + throw new ProtocolException("Protocol version unparseable: " + chaltok[3]); } // handle the challenge according to the version it is @@ -463,7 +466,7 @@ public class MapiConnection extends Mone // byte-order of server is little-endian break; default: - throw new MCLParseException("Invalid byte-order: " + chaltok[5]); + throw new ProtocolException("Invalid byte-order: " + chaltok[5]); } // generate response
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBConnectionFactory.java @@ -2,7 +2,7 @@ package nl.cwi.monetdb.mcl.connection; import nl.cwi.monetdb.jdbc.MonetConnection; import nl.cwi.monetdb.jdbc.MonetDriver; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import java.io.File; import java.io.IOException; @@ -16,7 +16,8 @@ import java.util.Properties; */ public final class MonetDBConnectionFactory { - public static MonetConnection CreateMonetDBJDBCConnection(Properties props) throws SQLException, IllegalArgumentException { + public static MonetConnection CreateMonetDBJDBCConnection(Properties props) + throws SQLException, IllegalArgumentException { MonetConnection res; boolean isEmbedded = Boolean.parseBoolean(props.getProperty("embedded", "false")); @@ -103,7 +104,8 @@ public final class MonetDBConnectionFact //initialize the debugging stuff if so if (debug) { try { - String fname = props.getProperty("logfile", "monet_" + System.currentTimeMillis() + ".log"); + String fname = props.getProperty("logfile", "monet_" + + System.currentTimeMillis() + ".log"); File f = new File(fname); int ext = fname.lastIndexOf('.'); if (ext < 0) ext = fname.length(); @@ -133,12 +135,14 @@ public final class MonetDBConnectionFact } catch (IOException e) { if(!isEmbedded) { MapiConnection con = (MapiConnection) res; - throw new SQLException("Unable to connect (" + con.getHostname() + ":" + con.getPort() + "): " + e.getMessage(), "08006"); + throw new SQLException("Unable to connect (" + con.getHostname() + ":" + + con.getPort() + "): " + e.getMessage(), "08006"); } else { EmbeddedConnection em = (EmbeddedConnection) res; - throw new SQLException("Unable to connect the directory " + em.getDirectory() + ": " + e.getMessage(), "08006"); + throw new SQLException("Unable to connect the directory " + em.getDirectory() + ": " + + e.getMessage(), "08006"); } - } catch (MCLParseException e) { + } catch (ProtocolException e) { throw new SQLException(e.getMessage(), "08001"); } catch (MCLException e) { String[] connex = e.getMessage().split("\n");
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBLanguage.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/MonetDBLanguage.java @@ -6,7 +6,8 @@ package nl.cwi.monetdb.mcl.connection; public enum MonetDBLanguage { /** the SQL language */ - LANG_SQL(new byte[][]{"s".getBytes(), "\n;".getBytes(), "\n;\n".getBytes()}, new byte[][]{"X".getBytes(), null, "\nX".getBytes()}, "sql"), + LANG_SQL(new byte[][]{"s".getBytes(), "\n;".getBytes(), "\n;\n".getBytes()}, new byte[][]{"X".getBytes(), null, + "\nX".getBytes()}, "sql"), /** the MAL language (officially *NOT* supported) */ LANG_MAL(new byte[][]{null, ";\n".getBytes(), ";\n".getBytes()}, new byte[][]{null, null, null}, "mal"), /** an unknown language */
--- a/src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java +++ b/src/main/java/nl/cwi/monetdb/mcl/connection/SendThread.java @@ -41,8 +41,7 @@ public class SendThread extends Thread { private final Condition waiting = sendLock.newCondition(); /** - * Constructor which immediately starts this thread and sets it - * into daemon mode. + * Constructor which immediately starts this thread and sets it into daemon mode. * * @param out the socket to write to */ @@ -70,7 +69,8 @@ public class SendThread extends Thread { // state is QUERY here try { - protocol.writeNextCommand((templ[0] == null ? MonetDBLanguage.EmptyString : templ[0]), query, (templ[1] == null ? MonetDBLanguage.EmptyString : templ[1])); + protocol.writeNextCommand((templ[0] == null ? MonetDBLanguage.EmptyString : templ[0]), query, + (templ[1] == null ? MonetDBLanguage.EmptyString : templ[1])); } catch (IOException e) { error = e.getMessage(); } @@ -86,9 +86,8 @@ public class SendThread extends Thread { } /** - * Starts sending the given query over the given socket. Beware - * that the thread should be finished (can be assured by calling - * throwErrors()) before this method is called! + * Starts sending the given query over the given socket. Beware that the thread should be finished (can be assured + * by calling throwErrors()) before this method is called! * * @param templ the query template * @param query the query itself
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/AbstractProtocol.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/AbstractProtocol.java @@ -34,21 +34,24 @@ public abstract class AbstractProtocol<T public abstract StarterHeaders getNextStarterHeader(); - public abstract ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) throws MCLParseException; + public abstract ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, + int seqnr) throws ProtocolException; - public abstract UpdateResponse getNextUpdateResponse() throws MCLParseException; + public abstract UpdateResponse getNextUpdateResponse() throws ProtocolException; public SchemaResponse getNextSchemaResponse() { return new SchemaResponse(); } - public abstract AutoCommitResponse getNextAutoCommitResponse() throws MCLParseException; + public abstract AutoCommitResponse getNextAutoCommitResponse() throws ProtocolException; - public abstract DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) throws MCLParseException; + public abstract DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) + throws ProtocolException; - public abstract TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws MCLParseException; + public abstract TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) + throws ProtocolException; - public abstract int parseTupleLine(Object line, Object[] values, int[] typesMap) throws MCLParseException; + public abstract int parseTupleLine(Object line, Object[] values, int[] typesMap) throws ProtocolException; public abstract String getRemainingStringLine(int startIndex);
rename from src/main/java/nl/cwi/monetdb/mcl/protocol/MCLParseException.java rename to src/main/java/nl/cwi/monetdb/mcl/protocol/ProtocolException.java --- a/src/main/java/nl/cwi/monetdb/mcl/protocol/MCLParseException.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/ProtocolException.java @@ -11,23 +11,23 @@ package nl.cwi.monetdb.mcl.protocol; import java.text.ParseException; /** - * When an MCLParseException is thrown, the MCL protocol is violated by + * When an ProtocolException is thrown, the MCL protocol is violated by * the sender. In general a stream reader throws an - * MCLParseException as soon as something that is read cannot be + * ProtocolException as soon as something that is read cannot be * understood or does not conform to the specifications (e.g. a * missing field). The instance that throws the exception will try to * give an error offset whenever possible. Alternatively it makes sure * that the error message includes the offending data read. */ -public class MCLParseException extends ParseException { +public class ProtocolException extends ParseException { private static final long serialVersionUID = 1L; - public MCLParseException(String e) { + public ProtocolException(String e) { super(e, -1); } - public MCLParseException(String e, int offset) { + public ProtocolException(String e, int offset) { super(e, offset); } }
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/ServerResponses.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/ServerResponses.java @@ -5,6 +5,8 @@ package nl.cwi.monetdb.mcl.protocol; */ public enum ServerResponses { + /* Please don't change the order */ + /** "there is currently no line", or the the type is unknown is represented by UNKNOWN */ UNKNOWN, /** a line starting with ! indicates ERROR */
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/StarterHeaders.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/StarterHeaders.java @@ -5,6 +5,8 @@ package nl.cwi.monetdb.mcl.protocol; */ public enum StarterHeaders { + /* Please don't change the order */ + /** A parse response (not handled) */ Q_PARSE, /** A tabular response (typical ResultSet) */
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/embedded/EmbeddedProtocol.java @@ -2,7 +2,7 @@ package nl.cwi.monetdb.mcl.protocol.embe import nl.cwi.monetdb.jdbc.MonetConnection; import nl.cwi.monetdb.mcl.io.JDBCEmbeddedConnection; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.StarterHeaders; import nl.cwi.monetdb.mcl.protocol.TableResultHeaders; @@ -45,32 +45,32 @@ public class EmbeddedProtocol extends Ab } @Override - public ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) throws MCLParseException { + public ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) throws ProtocolException { return null; } @Override - public UpdateResponse getNextUpdateResponse() throws MCLParseException { + public UpdateResponse getNextUpdateResponse() throws ProtocolException { return null; } @Override - public AutoCommitResponse getNextAutoCommitResponse() throws MCLParseException { + public AutoCommitResponse getNextAutoCommitResponse() throws ProtocolException { return null; } @Override - public DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) throws MCLParseException { + public DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) throws ProtocolException { return null; } @Override - public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws MCLParseException { + public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws ProtocolException { return null; } @Override - public int parseTupleLine(Object line, Object[] values) throws MCLParseException { + public int parseTupleLine(Object line, Object[] values, int[] typesMap) throws ProtocolException { return 0; }
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/newmapi/NewMapiProtocol.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/newmapi/NewMapiProtocol.java @@ -2,7 +2,7 @@ package nl.cwi.monetdb.mcl.protocol.newm import nl.cwi.monetdb.jdbc.MonetConnection; import nl.cwi.monetdb.mcl.io.SocketConnection; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.StarterHeaders; import nl.cwi.monetdb.mcl.protocol.TableResultHeaders; @@ -17,7 +17,7 @@ import java.util.Map; /** * Created by ferreira on 11/30/16. */ -public class NewMapiProtocol extends AbstractProtocol { +public class NewMapiProtocol extends AbstractProtocol<Object[]> { private final SocketConnection connection; @@ -27,12 +27,11 @@ public class NewMapiProtocol extends Abs @Override public void fetchNextResponseData() { - } @Override - public Object getCurrentData() { - return null; + public Object[] getCurrentData() { + return new Object[0]; } @Override @@ -41,27 +40,32 @@ public class NewMapiProtocol extends Abs } @Override - public ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) throws MCLParseException { + public ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) throws ProtocolException { return null; } @Override - public UpdateResponse getNextUpdateResponse() throws MCLParseException { + public UpdateResponse getNextUpdateResponse() throws ProtocolException { return null; } @Override - public AutoCommitResponse getNextAutoCommitResponse() throws MCLParseException { + public AutoCommitResponse getNextAutoCommitResponse() throws ProtocolException { return null; } @Override - public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws MCLParseException { + public DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) throws ProtocolException { return null; } @Override - public int parseTupleLine(Object line, Object[] values) throws MCLParseException { + public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws ProtocolException { + return null; + } + + @Override + public int parseTupleLine(Object line, Object[] values, int[] typesMap) throws ProtocolException { return 0; } @@ -74,9 +78,4 @@ public class NewMapiProtocol extends Abs public void writeNextCommand(byte[] prefix, byte[] query, byte[] suffix) throws IOException { } - - @Override - public DataBlockResponse getNextDatablockResponse(Map rsresponses) throws MCLParseException { - return null; - } }
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiProtocol.java @@ -2,7 +2,7 @@ package nl.cwi.monetdb.mcl.protocol.oldm import nl.cwi.monetdb.jdbc.MonetConnection; import nl.cwi.monetdb.mcl.io.SocketConnection; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import nl.cwi.monetdb.mcl.protocol.StarterHeaders; @@ -13,7 +13,6 @@ import nl.cwi.monetdb.mcl.responses.Data import nl.cwi.monetdb.mcl.responses.ResultSetResponse; import java.io.IOException; -import java.sql.ResultSet; import java.util.Map; /** @@ -29,7 +28,7 @@ public class OldMapiProtocol extends Abs int currentPointer = 0; - final StringBuilder tupleLineBuilder; + private final StringBuilder tupleLineBuilder; public OldMapiProtocol(SocketConnection con) { this.connection = con; @@ -82,8 +81,8 @@ public class OldMapiProtocol extends Abs @Override public ResultSetResponse getNextResultSetResponse(MonetConnection con, MonetConnection.ResponseList list, int seqnr) - throws MCLParseException { - int id = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); + throws ProtocolException { + int id = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); //The order cannot be switched!! int tuplecount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); int columncount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); int rowcount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); @@ -91,20 +90,21 @@ public class OldMapiProtocol extends Abs } @Override - public UpdateResponse getNextUpdateResponse() throws MCLParseException { + public UpdateResponse getNextUpdateResponse() throws ProtocolException { int count = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); //The order cannot be switched!! String lastId = OldMapiStartOfHeaderParser.GetNextResponseDataAsString(this); return new UpdateResponse(lastId, count); } @Override - public AutoCommitResponse getNextAutoCommitResponse() throws MCLParseException { + public AutoCommitResponse getNextAutoCommitResponse() throws ProtocolException { boolean ac = OldMapiStartOfHeaderParser.GetNextResponseDataAsString(this).equals("t"); return new AutoCommitResponse(ac); } @Override - public DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) throws MCLParseException { + public DataBlockResponse getNextDatablockResponse(Map<Integer, ResultSetResponse> rsresponses) + throws ProtocolException { int id = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); int columncount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); int rowcount = OldMapiStartOfHeaderParser.GetNextResponseDataAsInt(this); @@ -118,13 +118,15 @@ public class OldMapiProtocol extends Abs } @Override - public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) throws MCLParseException { + public TableResultHeaders getNextTableHeader(Object line, String[] stringValues, int[] intValues) + throws ProtocolException { return OldMapiTableHeaderParser.GetNextTableHeader((StringBuilder) line, stringValues, intValues); } @Override - public int parseTupleLine(Object line, Object[] values, int[] typesMap) throws MCLParseException { - return OldMapiTupleLineParser.OldMapiParseTupleLine((StringBuilder) line, values, this.tupleLineBuilder, typesMap); + public int parseTupleLine(Object line, Object[] values, int[] typesMap) throws ProtocolException { + return OldMapiTupleLineParser.OldMapiParseTupleLine((StringBuilder) line, values, this.tupleLineBuilder, + typesMap); } @Override
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiStartOfHeaderParser.java @@ -1,6 +1,6 @@ package nl.cwi.monetdb.mcl.protocol.oldmapi; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.StarterHeaders; /** @@ -38,10 +38,10 @@ final class OldMapiStartOfHeaderParser { return res; } - static int GetNextResponseDataAsInt(OldMapiProtocol protocol) throws MCLParseException { + static int GetNextResponseDataAsInt(OldMapiProtocol protocol) throws ProtocolException { protocol.currentPointer++; if (!protocol.hasRemaining()) { - throw new MCLParseException("unexpected end of string", protocol.currentPointer - 1); + throw new ProtocolException("unexpected end of string", protocol.currentPointer - 1); } int tmp; char chr = protocol.builder.charAt(protocol.currentPointer); @@ -50,7 +50,7 @@ final class OldMapiStartOfHeaderParser { if (chr >= '0' && chr <= '9') { tmp = (int)chr - (int)'0'; } else { - throw new MCLParseException("expected a digit", protocol.currentPointer - 1); + throw new ProtocolException("expected a digit", protocol.currentPointer - 1); } while (protocol.hasRemaining()) { @@ -63,16 +63,16 @@ final class OldMapiStartOfHeaderParser { if (chr >= '0' && chr <= '9') { tmp += (int)chr - (int)'0'; } else { - throw new MCLParseException("expected a digit", protocol.currentPointer - 1); + throw new ProtocolException("expected a digit", protocol.currentPointer - 1); } } return tmp; } - static String GetNextResponseDataAsString(OldMapiProtocol protocol) throws MCLParseException { + static String GetNextResponseDataAsString(OldMapiProtocol protocol) throws ProtocolException { protocol.currentPointer++; if (!protocol.hasRemaining()) { - throw new MCLParseException("unexpected end of string", protocol.currentPointer - 1); + throw new ProtocolException("unexpected end of string", protocol.currentPointer - 1); } int cnt = 0, mark = protocol.currentPointer; char chr;
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTableHeaderParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTableHeaderParser.java @@ -1,6 +1,6 @@ package nl.cwi.monetdb.mcl.protocol.oldmapi; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.TableResultHeaders; /** @@ -8,7 +8,7 @@ import nl.cwi.monetdb.mcl.protocol.Table */ final class OldMapiTableHeaderParser { - static TableResultHeaders GetNextTableHeader(StringBuilder builder, String[] stringValues, int[] intValues) throws MCLParseException { + static TableResultHeaders GetNextTableHeader(StringBuilder builder, String[] stringValues, int[] intValues) throws ProtocolException { TableResultHeaders res = TableResultHeaders.UNKNOWN; int len = builder.length(), pos = 0; boolean foundChar = false, nameFound = false; @@ -39,7 +39,7 @@ final class OldMapiTableHeaderParser { } } if (!nameFound) - throw new MCLParseException("invalid header, no header name found", pos); + throw new ProtocolException("invalid header, no header name found", pos); // depending on the name of the header, we continue switch (builder.charAt(pos)) { @@ -65,7 +65,7 @@ final class OldMapiTableHeaderParser { } break; default: - throw new MCLParseException("unknown header: " + builder.substring(pos, len - pos)); + throw new ProtocolException("unknown header: " + builder.substring(pos, len - pos)); } return res; } @@ -83,7 +83,7 @@ final class OldMapiTableHeaderParser { stringValues[elem + 1] = builder.substring(start, stop - start); } - private static void GetIntValues(StringBuilder builder, int stop, int[] intValues) throws MCLParseException { + private static void GetIntValues(StringBuilder builder, int stop, int[] intValues) throws ProtocolException { int elem = 0, tmp = 0, start = 2; for (int i = start; i < stop; i++) { @@ -97,7 +97,7 @@ final class OldMapiTableHeaderParser { if (builder.charAt(i) >= '0' && builder.charAt(i) <= '9') { tmp += (int) builder.charAt(i) - (int)'0'; } else { - throw new MCLParseException("expected a digit in " + builder.toString() + " at " + i); + throw new ProtocolException("expected a digit in " + builder.toString() + " at " + i); } } }
--- a/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java +++ b/src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiTupleLineParser.java @@ -1,19 +1,29 @@ package nl.cwi.monetdb.mcl.protocol.oldmapi; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.jdbc.MonetBlob; +import nl.cwi.monetdb.jdbc.MonetClob; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Date; +import java.sql.Types; +import java.text.ParseException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; /** * Created by ferreira on 12/6/16. */ final class OldMapiTupleLineParser { - static int OldMapiParseTupleLine(StringBuilder line, Object[] values, StringBuilder helper, int[] typesMap) throws MCLParseException { + static int OldMapiParseTupleLine(StringBuilder line, Object[] values, StringBuilder helper, int[] jDBCTypesMap) throws ProtocolException { int len = line.length(); // first detect whether this is a single value line (=) or a real tuple ([) if (line.charAt(0) == '=') { if (values.length != 1) { - throw new MCLParseException(values.length + " columns expected, but only single value found"); + throw new ProtocolException(values.length + " columns expected, but only single value found"); } // return the whole string but the leading = values[0] = line.substring(1); @@ -109,12 +119,13 @@ final class OldMapiTupleLineParser { } // put the unescaped string in the right place - values[column++] = helper.toString(); + values[column] = OldMapiStringToJavaObjectConverter(helper.toString(), jDBCTypesMap[column]); } else if ((i - 1) - cursor == 4 && line.indexOf("NULL", cursor) == cursor) { - values[column++] = null; + values[column] = null; } else { - values[column++] = line.substring(cursor, i - 1); + values[column] = OldMapiStringToJavaObjectConverter(line.substring(cursor, i - 1), jDBCTypesMap[column]); } + column++; cursor = i + 1; } // reset escaped flag @@ -124,8 +135,75 @@ final class OldMapiTupleLineParser { } // 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>")); - + throw new ProtocolException("illegal result length: " + column + "\nlast read: " + (column > 0 ? values[column - 1] : "<none>")); return column; } + + private static final SimpleDateFormat DateParser = new SimpleDateFormat("yyyy-MM-dd"); + + private static final SimpleDateFormat TimeParser = new SimpleDateFormat("HH:mm:ss"); + + private static final SimpleDateFormat TimestampParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private static byte[] BinaryBlobConverter(String toParse) { + int len = toParse.length() / 2; + byte[] res = new byte[len]; + for (int i = 0; i < len; i++) { + res[i] = (byte) Integer.parseInt(toParse.substring(2 * i, (2 * i) + 2), 16); + } + return res; + } + + private static Object OldMapiStringToJavaObjectConverter(String toParse, int jDBCMapping) throws ProtocolException { + switch (jDBCMapping) { + case Types.BIGINT: + return Long.parseLong(toParse); + case Types.BLOB: + return new MonetBlob(BinaryBlobConverter(toParse)); + case Types.BINARY: + return BinaryBlobConverter(toParse); + case Types.BOOLEAN: + return Boolean.parseBoolean(toParse); + case Types.CHAR: + return toParse; + case Types.CLOB: + return new MonetClob(toParse); + case Types.DATE: + try { + return DateParser.parse(toParse); + } catch (ParseException e) { + throw new ProtocolException(e.getMessage()); + } + case Types.DECIMAL: + return new BigDecimal(toParse); + case Types.DOUBLE: + return Double.parseDouble(toParse); + case Types.NUMERIC: + return new BigInteger(toParse); + case Types.INTEGER: + return Integer.parseInt(toParse); + case Types.REAL: + return Float.parseFloat(toParse); + case Types.SMALLINT: + return Short.parseShort(toParse); + case Types.TIME: + try { + return TimeParser.parse(toParse); + } catch (ParseException e) { + throw new ProtocolException(e.getMessage()); + } + case Types.TIMESTAMP: + try { + return TimestampParser.parse(toParse); + } catch (ParseException e) { + throw new ProtocolException(e.getMessage()); + } + case Types.TINYINT: + return Byte.parseByte(toParse); + case Types.VARCHAR: + return toParse; + default: + return null; + } + } }
--- a/src/main/java/nl/cwi/monetdb/mcl/responses/DataBlockResponse.java +++ b/src/main/java/nl/cwi/monetdb/mcl/responses/DataBlockResponse.java @@ -1,7 +1,7 @@ package nl.cwi.monetdb.mcl.responses; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import java.sql.SQLException; @@ -37,7 +37,8 @@ public class DataBlockResponse implement private final int[] jdbcSQLTypes; /** - * Constructs a DataBlockResponse object + * Constructs a DataBlockResponse object. + * * @param rowcount the number of rows * @param columncount the number of columns * @param forward whether this is a forward only result @@ -56,11 +57,12 @@ public class DataBlockResponse implement * * @param line the header line as String * @param response the line type according to the MAPI protocol - * @throws MCLParseException If the result line is not expected + * @throws ProtocolException If the result line is not expected */ - public void addLine(ServerResponses response, Object line) throws MCLParseException { + @Override + public void addLine(ServerResponses response, Object line) throws ProtocolException { if (response != ServerResponses.RESULT) - throw new MCLParseException("protocol violation: unexpected line in data block: " + line.toString()); + throw new ProtocolException("protocol violation: unexpected line in data block: " + line.toString()); // add to the backing array Object[] next = this.data[++this.pos]; this.protocol.parseTupleLine(line, next, this.jdbcSQLTypes); @@ -79,15 +81,16 @@ public class DataBlockResponse implement /** * Indicates that no more header lines will be added to this Response implementation. In most cases this is a - * redundant operation because the data array is full. However... it can happen that this is NOT the case! + * redundant operation because the data array is full. However... it can happen that this is NOT the case! * * @throws SQLException if not all rows are filled */ @Override public void complete() throws SQLException { - if ((pos + 1) != data.length) - throw new SQLException("Inconsistent state detected! Current block capacity: " + data.length + - ", block usage: " + (pos + 1) + ". Did MonetDB send what it promised to?", "M0M10"); + if ((pos + 1) != data.length) { + throw new SQLException("Inconsistent state detected! Current block capacity: " + data.length + + ", block usage: " + (pos + 1) + ". Did MonetDB send what it promised to?", "M0M10"); + } } /** @@ -102,7 +105,7 @@ public class DataBlockResponse implement } /** - * Retrieves the required row. Warning: if the requested rows is out of bounds, an IndexOutOfBoundsException will + * Retrieves the required row. Warning: if the requested rows is out of bounds, an IndexOutOfBoundsException will * be thrown. * * @param line the row to retrieve
--- a/src/main/java/nl/cwi/monetdb/mcl/responses/IIncompleteResponse.java +++ b/src/main/java/nl/cwi/monetdb/mcl/responses/IIncompleteResponse.java @@ -1,6 +1,6 @@ package nl.cwi.monetdb.mcl.responses; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import java.sql.SQLException; @@ -26,5 +26,5 @@ public interface IIncompleteResponse ext */ void complete() throws SQLException; - void addLine(ServerResponses response, Object line) throws MCLParseException; + void addLine(ServerResponses response, Object line) throws ProtocolException; }
--- a/src/main/java/nl/cwi/monetdb/mcl/responses/ResultSetResponse.java +++ b/src/main/java/nl/cwi/monetdb/mcl/responses/ResultSetResponse.java @@ -3,7 +3,7 @@ package nl.cwi.monetdb.mcl.responses; import nl.cwi.monetdb.jdbc.MonetConnection; import nl.cwi.monetdb.jdbc.MonetDriver; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; -import nl.cwi.monetdb.mcl.protocol.MCLParseException; +import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import java.sql.ResultSet; @@ -52,7 +52,6 @@ public class ResultSetResponse implement private byte isSet; /** Whether this Response is closed */ private boolean closed; - /** The connection belonging for this ResultSetResponse */ private MonetConnection con; /** The Connection that we should use when requesting a new block */ @@ -67,8 +66,7 @@ public class ResultSetResponse implement private final DataBlockResponse[] resultBlocks; /** - * Sole constructor, which requires a MonetConnection parent to - * be given. + * Sole constructor, which requires a MonetConnection parent to be given. * * @param id the ID of the result set * @param tuplecount the total number of tuples in the result set @@ -127,10 +125,10 @@ public class ResultSetResponse implement private void populateJdbcSQLTypesArray() { for (int i = 0; i < this.type.length; i++) { int javaSQLtype = MonetDriver.getJavaType(this.type[i]); + if (javaSQLtype == Types.BLOB && con.getBlobAsBinary()) { + javaSQLtype = Types.BINARY; + } this.JdbcSQLTypes[i] = javaSQLtype; - if (javaSQLtype == Types.BLOB && con.getBlobAsBinary()) { - this.JdbcSQLTypes[i] = Types.BINARY; - } } } @@ -269,14 +267,15 @@ public class ResultSetResponse implement * underlying DataResponse. * * @param line the string that contains the header - * @throws MCLParseException if has a wrong header + * @throws ProtocolException if has a wrong header */ - public void addLine(ServerResponses response, Object line) throws MCLParseException { + @Override + public void addLine(ServerResponses response, Object line) throws ProtocolException { if (this.isSet >= IsSetFinalValue) { this.resultBlocks[0].addLine(response, line); } if (response != ServerResponses.HEADER) { - throw new MCLParseException("header expected, got: " + response.toString()); + throw new ProtocolException("header expected, got: " + response.toString()); } else { //we will always pass the tableNames pointer switch (con.getProtocol().getNextTableHeader(line, this.tableNames, this.columnLengths)) { @@ -300,14 +299,12 @@ public class ResultSetResponse implement } /** - * Returns a line from the cache. If the line is already present in the - * cache, it is returned, if not appropriate actions are taken to make - * sure the right block is being fetched and as soon as the requested - * line is fetched it is returned. + * Returns a line from the cache. If the line is already present in the cache, it is returned, if not appropriate + * actions are taken to make sure the right block is being fetched and as soon as the requested line is fetched it + * is returned. * * @param row the row in the result set to return - * @return the exact row read as requested or null if the requested row - * is out of the scope of the result set + * @return the exact row read as requested or null if the requested row is out of the scope of the result set * @throws SQLException if an database error occurs */ public Object[] getLine(int row) throws SQLException { @@ -321,41 +318,30 @@ public class ResultSetResponse implement DataBlockResponse rawr; // load block if appropriate if ((rawr = resultBlocks[block]) == null) { - /// TODO: ponder about a maximum number of blocks to keep - /// in memory when dealing with random access to - /// reduce memory blow-up + // TODO: ponder about a maximum number of blocks to keep in memory when dealing with random access to + // reduce memory blow-up - // if we're running forward only, we can discard the resultset - // block loaded + // if we're running forward only, we can discard the resultset block loaded if (parent.getRstype() == ResultSet.TYPE_FORWARD_ONLY) { for (int i = 0; i < block; i++) resultBlocks[i] = null; if (MonetConnection.GetSeqCounter() - 1 == seqnr && !cacheSizeSetExplicitly && tuplecount - row > cacheSize && cacheSize < MonetConnection.GetDefFetchsize() * 10) { - // there has no query been issued after this - // one, so we can consider this an uninterrupted - // continuation request. Let's once increase - // the cacheSize as it was not explicitly set, - // since the chances are high that we won't - // bother anyone else by doing so, and just - // gaining some performance. + // there has no query been issued after this one, so we can consider this an uninterrupted + // continuation request. Let's once increase the cacheSize as it was not explicitly set, + // since the chances are high that we won't bother anyone else by doing so, and just gaining + // some performance. - // store the previous position in the - // blockOffset variable + // store the previous position in the blockOffset variable blockOffset += cacheSize; // increase the cache size (a lot) cacheSize *= 10; - // by changing the cacheSize, we also - // change the block measures. Luckily - // we don't care about previous blocks - // because we have a forward running - // pointer only. However, we do have - // to recalculate the block number, to - // ensure the next call to find this - // new block. + // by changing the cacheSize, we also change the block measures. Luckily we don't care about + // previous blocks because we have a forward running pointer only. However, we do have to + // recalculate the block number, to ensure the next call to find this new block. block = (row - blockOffset) / cacheSize; blockLine = (row - blockOffset) % cacheSize; } @@ -373,15 +359,14 @@ public class ResultSetResponse implement } /** - * Closes this Response by sending an Xclose to the server indicating - * that the result can be closed at the server side as well. + * Closes this Response by sending an Xclose to the server indicating that the result can be closed at the server + * side as well. */ @Override public void close() { if (closed) return; - // send command to server indicating we're done with this - // result only if we had an ID in the header and this result - // was larger than the reply size + // send command to server indicating we're done with this result only if we had an ID in the header and this + // result was larger than the reply size try { if (destroyOnClose) { con.sendControlCommand("close " + id);