Mercurial > hg > monetdb-java
view src/main/java/nl/cwi/monetdb/mcl/protocol/oldmapi/OldMapiDataBlockResponse.java @ 120:02f560eb3cf2 embedded
Major change in the Datablock response. Removed the arrays creation in the Embedded connection, so it will run much faster now. It can be possible to do it as well in the MAPI connection, but in the way the Old Mapi Protocol is designed, it will be very complicated (ByteBuffers are designed to work with binary data instead of textual data :S). I think it's better to wait for the new protocol, which will be much faster and easier to parse.
author | Pedro Ferreira <pedro.ferreira@monetdbsolutions.com> |
---|---|
date | Tue, 28 Feb 2017 16:57:27 +0100 (2017-02-28) |
parents | |
children | 92bac8379d06 |
line wrap: on
line source
package nl.cwi.monetdb.mcl.protocol.oldmapi; import nl.cwi.monetdb.jdbc.MonetBlob; import nl.cwi.monetdb.jdbc.MonetClob; import nl.cwi.monetdb.mcl.connection.helpers.TimestampHelper; import nl.cwi.monetdb.mcl.protocol.AbstractProtocol; import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.protocol.ServerResponses; import nl.cwi.monetdb.mcl.responses.AbstractDataBlockResponse; import java.math.BigDecimal; import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Arrays; import java.util.Calendar; /** * DataBlockResponse for an Old MAPI connection. * * @author Fabin Groffen, Pedro Ferreira */ public class OldMapiDataBlockResponse extends AbstractDataBlockResponse { /** The array to keep the data in */ private Object[] data; /** The counter which keeps the current position in the lines array */ private int pos; /** The last parsed nanos values for timestamps */ private int lastNanos; OldMapiDataBlockResponse(int rowcount, int columncount, AbstractProtocol protocol, int[] JdbcSQLTypes) { super(rowcount, protocol, JdbcSQLTypes); this.pos = -1; this.data = new Object[columncount]; } @Override public void addLines(AbstractProtocol protocol) throws ProtocolException { int csrh = protocol.getCurrentServerResponse(); if (csrh != ServerResponses.RESULT) { throw new ProtocolException("protocol violation: unexpected line in data block: " + protocol.getRemainingStringLine(0)); } if(this.pos == -1) { //if it's the first line, initialize the matrix int numberOfColumns = this.data.length; for (int i = 0 ; i < numberOfColumns ; i++) { switch (this.jdbcSQLTypes[i]) { case Types.INTEGER: this.data[i] = new int[this.rowcount]; break; case Types.BOOLEAN: case Types.TINYINT: this.data[i] = new byte[this.rowcount]; break; case Types.SMALLINT: this.data[i] = new short[this.rowcount]; break; case Types.REAL: this.data[i] = new float[this.rowcount]; break; case Types.DOUBLE: this.data[i] = new double[this.rowcount]; break; case Types.BIGINT: this.data[i] = new long[this.rowcount]; break; case Types.DATE: case Types.TIME: case Types.TIME_WITH_TIMEZONE: this.data[i] = new Calendar[this.rowcount]; break; case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: this.data[i] = new TimestampHelper[this.rowcount]; break; case Types.NUMERIC: case Types.DECIMAL: this.data[i] = new BigDecimal[this.rowcount]; break; case Types.BLOB: this.data[i] = new MonetBlob[this.rowcount]; break; case Types.CLOB: this.data[i] = new MonetClob[this.rowcount]; break; case Types.LONGVARBINARY: this.data[i] = new byte[this.rowcount][]; break; default: //CHAR, VARCHAR, OTHER this.data[i] = new String[this.rowcount]; } } } // add to the backing array int nextPos = this.pos + 1; this.pos = ((OldMapiProtocol)this.protocol).parseTupleLines(nextPos, this.jdbcSQLTypes, this.data); } /** * Returns whether this Response expects more lines to be added to it. * * @return true if a next line should be added, false otherwise */ @Override public boolean wantsMore() { // remember: pos is the value already stored return (this.pos + 1) < this.rowcount; } /** * Instructs the Response implementation to close and do the necessary clean up procedures. */ @Override public void close() { // feed all rows to the garbage collector int numberOfColumns = this.data.length; for (int i = 0; i < numberOfColumns; i++) { data[i] = null; } data = null; } /** * Checks if a value in the current row is null. * * @param column The column index starting from 0 * @return If the value is null or not. */ private boolean checkValueIsNull(int column) { switch (this.jdbcSQLTypes[column]) { case Types.BOOLEAN: case Types.TINYINT: this.lastReadWasNull = ((byte[]) this.data[column])[this.blockLine] == Byte.MIN_VALUE; break; case Types.SMALLINT: this.lastReadWasNull = ((short[]) this.data[column])[this.blockLine] == Short.MIN_VALUE; break; case Types.INTEGER: this.lastReadWasNull = ((int[]) this.data[column])[this.blockLine] == Integer.MIN_VALUE; break; case Types.BIGINT: this.lastReadWasNull = ((long[]) this.data[column])[this.blockLine] == Long.MIN_VALUE; break; case Types.REAL: this.lastReadWasNull = ((float[]) this.data[column])[this.blockLine] == Float.MIN_VALUE; break; case Types.DOUBLE: this.lastReadWasNull = ((double[]) this.data[column])[this.blockLine] == Double.MIN_VALUE; break; default: this.lastReadWasNull = ((Object[]) this.data[column])[this.blockLine] == null; } return this.lastReadWasNull; } @Override public boolean getBooleanValue(int column) { return !this.checkValueIsNull(column) && ((byte[]) this.data[column])[this.blockLine] == 1; } @Override public byte getByteValue(int column) { if(this.checkValueIsNull(column)) { return 0; } return ((byte[]) this.data[column])[this.blockLine]; } @Override public short getShortValue(int column) { if(this.checkValueIsNull(column)) { return 0; } return ((short[]) this.data[column])[this.blockLine]; } @Override public int getIntValue(int column) { if(this.checkValueIsNull(column)) { return 0; } return ((int[]) this.data[column])[this.blockLine]; } @Override public long getLongValue(int column) { if(this.checkValueIsNull(column)) { return 0; } return ((long[]) this.data[column])[this.blockLine]; } @Override public float getFloatValue(int column) { if(this.checkValueIsNull(column)) { return 0.0f; } return ((float[]) this.data[column])[this.blockLine]; } @Override public double getDoubleValue(int column) { if(this.checkValueIsNull(column)) { return 0.0f; } return ((double[]) this.data[column])[this.blockLine]; } @Override public Object getObjectValue(int column) { if(this.checkValueIsNull(column)) { return null; } return ((Object[]) this.data[column])[this.blockLine]; } @Override public String getValueAsString(int column) { switch (this.jdbcSQLTypes[column]) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.OTHER: return ((String[]) this.data[column])[this.blockLine]; case Types.LONGVARBINARY: return Arrays.toString(((byte[][]) this.data[column])[this.blockLine]); case Types.BOOLEAN: return ((byte[]) this.data[column])[this.blockLine] == 1 ? "true" : "false"; case Types.TINYINT: return Byte.toString(((byte[]) this.data[column])[this.blockLine]); case Types.SMALLINT: return Short.toString(((short[]) this.data[column])[this.blockLine]); case Types.INTEGER: return Integer.toString(((int[]) this.data[column])[this.blockLine]); case Types.BIGINT: return Long.toString(((long[]) this.data[column])[this.blockLine]); case Types.REAL: return Float.toString(((float[]) this.data[column])[this.blockLine]); case Types.DOUBLE: return Double.toString(((double[]) this.data[column])[this.blockLine]); case Types.DATE: Date aux1 = new Date(((Calendar[]) this.data[column])[this.blockLine].getTimeInMillis()); return protocol.getMonetDate().format(aux1); case Types.TIME: Time aux2 = new Time(((Calendar[]) this.data[column])[this.blockLine].getTimeInMillis()); return protocol.getMonetTimePrinter().format(aux2); case Types.TIME_WITH_TIMEZONE: Time aux3 = new Time(((Calendar[]) this.data[column])[this.blockLine].getTimeInMillis()); return protocol.getMonetTimeTzPrinter().format(aux3); case Types.TIMESTAMP: TimestampHelper thel = ((TimestampHelper[]) this.data[column])[this.blockLine]; Timestamp aux4 = thel.getTimestamp(); this.lastNanos = thel.getNanoseconds(); return protocol.getMonetTimestampPrinter().format(aux4); case Types.TIMESTAMP_WITH_TIMEZONE: TimestampHelper thelper = ((TimestampHelper[]) this.data[column])[this.blockLine]; Timestamp aux5 = thelper.getTimestamp(); this.lastNanos = thelper.getNanoseconds(); return protocol.getMonetTimestampTzPrinter().format(aux5); default: //BLOB, CLOB, BigDecimal return ((Object[]) this.data[column])[this.blockLine].toString(); } } @Override public Object getValueAsObject(int column) { switch (this.jdbcSQLTypes[column]) { case Types.BOOLEAN: return ((byte[]) this.data[column])[this.blockLine] == 1; case Types.TINYINT: return ((byte[]) this.data[column])[this.blockLine]; case Types.SMALLINT: return ((short[]) this.data[column])[this.blockLine]; case Types.INTEGER: return ((int[]) this.data[column])[this.blockLine]; case Types.BIGINT: return ((long[]) this.data[column])[this.blockLine]; case Types.REAL: return ((float[]) this.data[column])[this.blockLine]; case Types.DOUBLE: return ((double[]) this.data[column])[this.blockLine]; case Types.TIMESTAMP: case Types.TIMESTAMP_WITH_TIMEZONE: TimestampHelper thelper = ((TimestampHelper[]) this.data[column])[this.blockLine]; this.lastNanos = thelper.getNanoseconds(); return thelper.getCalendar(); default: return ((Object[]) this.data[column])[this.blockLine]; } } @Override public int getLastNanos() { return this.lastNanos; } }