| package org.mariadb.jdbc.client.result.rowdecoder; |
| |
| import static org.mariadb.jdbc.client.result.Result.NULL_LENGTH; |
| |
| import java.sql.Date; |
| import java.sql.SQLException; |
| import java.sql.Time; |
| import java.sql.Timestamp; |
| import java.util.Calendar; |
| import org.mariadb.jdbc.Configuration; |
| import org.mariadb.jdbc.client.ColumnDecoder; |
| import org.mariadb.jdbc.client.impl.StandardReadableByteBuf; |
| import org.mariadb.jdbc.client.util.MutableInt; |
| import org.mariadb.jdbc.plugin.Codec; |
| |
| /** BINARY rows decoder */ |
| public class BinaryRowDecoder implements RowDecoder { |
| |
| /** |
| * Binary decode data according to data type. |
| * |
| * @param codec current codec |
| * @param cal calendar |
| * @param rowBuf row buffer |
| * @param fieldLength field length |
| * @param metadataList metadatas |
| * @param fieldIndex field index |
| * @return default object according to metadata |
| * @param <T> Codec default return type |
| * @throws SQLException if any decoding error occurs |
| */ |
| public <T> T decode( |
| Codec<T> codec, |
| Calendar cal, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength, |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex) |
| throws SQLException { |
| return codec.decodeBinary(rowBuf, fieldLength, metadataList[fieldIndex.get()], cal); |
| } |
| |
| @Override |
| public Object defaultDecode( |
| Configuration conf, |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].getDefaultBinary(conf, rowBuf, fieldLength); |
| } |
| |
| public String decodeString( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeStringBinary(rowBuf, fieldLength, null); |
| } |
| |
| public byte decodeByte( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeByteBinary(rowBuf, fieldLength); |
| } |
| |
| public boolean decodeBoolean( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeBooleanBinary(rowBuf, fieldLength); |
| } |
| |
| public Date decodeDate( |
| ColumnDecoder[] metadataList, |
| MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength, |
| Calendar cal) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeDateBinary(rowBuf, fieldLength, cal); |
| } |
| |
| public Time decodeTime( |
| ColumnDecoder[] metadataList, |
| MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength, |
| Calendar cal) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeTimeBinary(rowBuf, fieldLength, cal); |
| } |
| |
| public Timestamp decodeTimestamp( |
| ColumnDecoder[] metadataList, |
| MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength, |
| Calendar cal) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeTimestampBinary(rowBuf, fieldLength, cal); |
| } |
| |
| public short decodeShort( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeShortBinary(rowBuf, fieldLength); |
| } |
| |
| public int decodeInt( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeIntBinary(rowBuf, fieldLength); |
| } |
| |
| public long decodeLong( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeLongBinary(rowBuf, fieldLength); |
| } |
| |
| public float decodeFloat( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeFloatBinary(rowBuf, fieldLength); |
| } |
| |
| public double decodeDouble( |
| ColumnDecoder[] metadataList, |
| final MutableInt fieldIndex, |
| StandardReadableByteBuf rowBuf, |
| int fieldLength) |
| throws SQLException { |
| return metadataList[fieldIndex.get()].decodeDoubleBinary(rowBuf, fieldLength); |
| } |
| |
| public boolean wasNull(byte[] nullBitmap, final MutableInt fieldIndex, int fieldLength) { |
| return (nullBitmap[(fieldIndex.get() + 2) / 8] & (1 << ((fieldIndex.get() + 2) % 8))) > 0; |
| } |
| |
| /** |
| * Set length and pos indicator to asked index. |
| * |
| * @param newIndex index (0 is first). |
| */ |
| @Override |
| public int setPosition( |
| int newIndex, |
| final MutableInt fieldIndex, |
| int maxIndex, |
| StandardReadableByteBuf rowBuf, |
| byte[] nullBitmap, |
| ColumnDecoder[] metadataList) { |
| |
| if (fieldIndex.get() >= newIndex) { |
| fieldIndex.set(0); |
| rowBuf.pos(1); |
| rowBuf.readBytes(nullBitmap); |
| } else { |
| fieldIndex.incrementAndGet(); |
| if (fieldIndex.get() == 0) { |
| // skip header + null-bitmap |
| rowBuf.pos(1); |
| rowBuf.readBytes(nullBitmap); |
| } |
| } |
| |
| while (fieldIndex.get() < newIndex) { |
| if ((nullBitmap[(fieldIndex.get() + 2) / 8] & (1 << ((fieldIndex.get() + 2) % 8))) == 0) { |
| // skip bytes |
| switch (metadataList[fieldIndex.get()].getType()) { |
| case BIGINT: |
| case DOUBLE: |
| rowBuf.skip(8); |
| break; |
| |
| case INTEGER: |
| case MEDIUMINT: |
| case FLOAT: |
| rowBuf.skip(4); |
| break; |
| |
| case SMALLINT: |
| case YEAR: |
| rowBuf.skip(2); |
| break; |
| |
| case TINYINT: |
| rowBuf.skip(1); |
| break; |
| |
| default: |
| rowBuf.skipLengthEncoded(); |
| break; |
| } |
| } |
| fieldIndex.incrementAndGet(); |
| } |
| |
| if (wasNull(nullBitmap, fieldIndex, 0)) { |
| return NULL_LENGTH; |
| } |
| |
| // read asked field position and length |
| switch (metadataList[fieldIndex.get()].getType()) { |
| case BIGINT: |
| case DOUBLE: |
| return 8; |
| |
| case INTEGER: |
| case MEDIUMINT: |
| case FLOAT: |
| return 4; |
| |
| case SMALLINT: |
| case YEAR: |
| return 2; |
| |
| case TINYINT: |
| return 1; |
| |
| default: |
| // field with variable length |
| byte len = rowBuf.readByte(); |
| switch (len) { |
| case (byte) 252: |
| // length is encoded on 3 bytes (0xfc header + 2 bytes indicating length) |
| return rowBuf.readUnsignedShort(); |
| |
| case (byte) 253: |
| // length is encoded on 4 bytes (0xfd header + 3 bytes indicating length) |
| return rowBuf.readUnsignedMedium(); |
| |
| case (byte) 254: |
| // length is encoded on 9 bytes (0xfe header + 8 bytes indicating length) |
| return (int) rowBuf.readLong(); |
| default: |
| return len & 0xff; |
| } |
| } |
| } |
| } |