| // SPDX-License-Identifier: LGPL-2.1-or-later |
| // Copyright (c) 2012-2014 Monty Program Ab |
| // Copyright (c) 2015-2021 MariaDB Corporation Ab |
| |
| package org.mariadb.jdbc.client.result; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Reader; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.math.RoundingMode; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.sql.*; |
| import java.sql.Date; |
| import java.util.*; |
| import java.util.concurrent.locks.ReentrantLock; |
| import org.mariadb.jdbc.Configuration; |
| import org.mariadb.jdbc.client.*; |
| import org.mariadb.jdbc.client.impl.StandardReadableByteBuf; |
| import org.mariadb.jdbc.client.result.rowdecoder.BinaryRowDecoder; |
| import org.mariadb.jdbc.client.result.rowdecoder.RowDecoder; |
| import org.mariadb.jdbc.client.result.rowdecoder.TextRowDecoder; |
| import org.mariadb.jdbc.client.util.MutableInt; |
| import org.mariadb.jdbc.export.ExceptionFactory; |
| import org.mariadb.jdbc.message.server.ErrorPacket; |
| import org.mariadb.jdbc.plugin.Codec; |
| import org.mariadb.jdbc.plugin.codec.*; |
| import org.mariadb.jdbc.util.constants.ServerStatus; |
| |
| /** Result-set common */ |
| public abstract class Result implements ResultSet, Completion { |
| private static BinaryRowDecoder BINARY_ROW_DECODER = new BinaryRowDecoder(); |
| private static TextRowDecoder TEXT_ROW_DECODER = new TextRowDecoder(); |
| /** null length value */ |
| public static final int NULL_LENGTH = -1; |
| |
| private final int maxIndex; |
| private final boolean closeOnCompletion; |
| private boolean forceAlias; |
| private final boolean traceEnable; |
| |
| /** result-set type */ |
| protected final int resultSetType; |
| |
| /** connection exception factory */ |
| protected final ExceptionFactory exceptionFactory; |
| |
| /** packet reader */ |
| protected final org.mariadb.jdbc.client.socket.Reader reader; |
| |
| /** connection context */ |
| protected final Context context; |
| |
| /** columns metadata */ |
| protected final ColumnDecoder[] metadataList; |
| |
| /** binary/text row decoder */ |
| protected final RowDecoder rowDecoder; |
| |
| /** data size */ |
| protected int dataSize = 0; |
| |
| /** rows */ |
| protected byte[][] data; |
| |
| private byte[] nullBitmap; |
| |
| /** reusable row buffer decoder */ |
| protected final StandardReadableByteBuf rowBuf = new StandardReadableByteBuf(null, 0); |
| |
| private int fieldLength; |
| |
| /** mutable field index */ |
| protected MutableInt fieldIndex = new MutableInt(); |
| |
| private Map<String, Integer> mapper = null; |
| |
| /** is fully loaded */ |
| protected boolean loaded; |
| |
| /** is an output parameter result-set */ |
| protected boolean outputParameter; |
| |
| /** current row pointer */ |
| protected int rowPointer = -1; |
| |
| /** is result-set closed */ |
| protected boolean closed; |
| |
| /** statement that initiate this result */ |
| protected Statement statement; |
| |
| /** row number limit */ |
| protected long maxRows; |
| |
| /** |
| * Constructor for server's data |
| * |
| * @param stmt statement that initiate this result |
| * @param binaryProtocol binary encoded rows |
| * @param maxRows row number limit |
| * @param metadataList columns metadata |
| * @param reader packet reader |
| * @param context connection context |
| * @param resultSetType result-set type |
| * @param closeOnCompletion close statement on completion |
| * @param traceEnable logger enabled |
| */ |
| public Result( |
| org.mariadb.jdbc.Statement stmt, |
| boolean binaryProtocol, |
| long maxRows, |
| ColumnDecoder[] metadataList, |
| org.mariadb.jdbc.client.socket.Reader reader, |
| Context context, |
| int resultSetType, |
| boolean closeOnCompletion, |
| boolean traceEnable) { |
| this.maxRows = maxRows; |
| this.statement = stmt; |
| this.closeOnCompletion = closeOnCompletion; |
| this.metadataList = metadataList; |
| this.maxIndex = this.metadataList.length; |
| this.reader = reader; |
| this.exceptionFactory = context.getExceptionFactory(); |
| this.context = context; |
| this.resultSetType = resultSetType; |
| this.traceEnable = traceEnable; |
| if (binaryProtocol) { |
| rowDecoder = BINARY_ROW_DECODER; |
| nullBitmap = new byte[(maxIndex + 9) / 8]; |
| } else { |
| rowDecoder = TEXT_ROW_DECODER; |
| } |
| } |
| |
| /** |
| * Internal constructed result-set |
| * |
| * @param metadataList column metadata |
| * @param data raw data |
| * @param context connection context |
| */ |
| public Result(ColumnDecoder[] metadataList, byte[][] data, Context context) { |
| this.metadataList = metadataList; |
| this.maxIndex = this.metadataList.length; |
| this.reader = null; |
| this.loaded = true; |
| this.exceptionFactory = context.getExceptionFactory(); |
| this.context = context; |
| this.data = data; |
| this.dataSize = data.length; |
| this.statement = null; |
| this.resultSetType = TYPE_FORWARD_ONLY; |
| this.closeOnCompletion = false; |
| this.traceEnable = false; |
| rowDecoder = TEXT_ROW_DECODER; |
| } |
| |
| /** |
| * Read new row |
| * |
| * @return true if fully loaded |
| * @throws IOException if any socket error occurs |
| * @throws SQLException for all other type of errors |
| */ |
| @SuppressWarnings("fallthrough") |
| protected boolean readNext() throws IOException, SQLException { |
| byte[] buf = reader.readPacket(traceEnable); |
| switch (buf[0]) { |
| case (byte) 0xFF: |
| loaded = true; |
| ErrorPacket errorPacket = new ErrorPacket(reader.readableBufFromArray(buf), context); |
| throw exceptionFactory.create( |
| errorPacket.getMessage(), errorPacket.getSqlState(), errorPacket.getErrorCode()); |
| |
| case (byte) 0xFE: |
| if ((context.isEofDeprecated() && buf.length < 16777215) |
| || (!context.isEofDeprecated() && buf.length < 8)) { |
| ReadableByteBuf readBuf = reader.readableBufFromArray(buf); |
| readBuf.skip(); // skip header |
| int serverStatus; |
| int warnings; |
| |
| if (!context.isEofDeprecated()) { |
| // EOF_Packet |
| warnings = readBuf.readUnsignedShort(); |
| serverStatus = readBuf.readUnsignedShort(); |
| } else { |
| // OK_Packet with a 0xFE header |
| readBuf.readLongLengthEncodedNotNull(); // skip update count |
| readBuf.readLongLengthEncodedNotNull(); // skip insert id |
| serverStatus = readBuf.readUnsignedShort(); |
| warnings = readBuf.readUnsignedShort(); |
| } |
| outputParameter = (serverStatus & ServerStatus.PS_OUT_PARAMETERS) != 0; |
| context.setServerStatus(serverStatus); |
| context.setWarning(warnings); |
| loaded = true; |
| return false; |
| } |
| |
| // continue reading rows |
| |
| default: |
| if (dataSize + 1 > data.length) { |
| growDataArray(); |
| } |
| data[dataSize++] = buf; |
| } |
| return true; |
| } |
| |
| /** |
| * Skip remaining rows to keep connection state ok, without needing remaining data. |
| * |
| * @throws IOException if socket error occurs |
| * @throws SQLException for other kind of error |
| */ |
| @SuppressWarnings("fallthrough") |
| protected void skipRemaining() throws IOException, SQLException { |
| while (true) { |
| ReadableByteBuf buf = reader.readReusablePacket(traceEnable); |
| switch (buf.getUnsignedByte()) { |
| case 0xFF: |
| loaded = true; |
| ErrorPacket errorPacket = new ErrorPacket(buf, context); |
| throw exceptionFactory.create( |
| errorPacket.getMessage(), errorPacket.getSqlState(), errorPacket.getErrorCode()); |
| |
| case 0xFE: |
| if ((context.isEofDeprecated() && buf.readableBytes() < 0xffffff) |
| || (!context.isEofDeprecated() && buf.readableBytes() < 8)) { |
| |
| buf.skip(); // skip header |
| int serverStatus; |
| int warnings; |
| |
| if (!context.isEofDeprecated()) { |
| // EOF_Packet |
| warnings = buf.readUnsignedShort(); |
| serverStatus = buf.readUnsignedShort(); |
| } else { |
| // OK_Packet with a 0xFE header |
| buf.readLongLengthEncodedNotNull(); // skip update count |
| buf.readLongLengthEncodedNotNull(); // skip insert id |
| serverStatus = buf.readUnsignedShort(); |
| warnings = buf.readUnsignedShort(); |
| } |
| outputParameter = (serverStatus & ServerStatus.PS_OUT_PARAMETERS) != 0; |
| context.setServerStatus(serverStatus); |
| context.setWarning(warnings); |
| loaded = true; |
| return; |
| } |
| } |
| } |
| } |
| |
| /** Grow data array. */ |
| private void growDataArray() { |
| int newCapacity = data.length + (data.length >> 1); |
| byte[][] newData = new byte[newCapacity][]; |
| System.arraycopy(data, 0, newData, 0, data.length); |
| data = newData; |
| } |
| |
| /** |
| * Position resultset to next row |
| * |
| * @return true if next row exists |
| * @throws SQLException if any error occurs |
| */ |
| @Override |
| public abstract boolean next() throws SQLException; |
| |
| /** |
| * Indicate of current result-set is a streaming result-set |
| * |
| * @return if streaming result-set |
| */ |
| public abstract boolean streaming(); |
| |
| /** |
| * Fetch remaining results. |
| * |
| * @throws SQLException if issue occurs during data retrieving |
| */ |
| public abstract void fetchRemaining() throws SQLException; |
| |
| /** |
| * Is result-set fully loaded or still streaming |
| * |
| * @return true if fully loaded |
| */ |
| public boolean loaded() { |
| return loaded; |
| } |
| |
| /** |
| * Does result-set contain output parameters |
| * |
| * @return true if containing output parameters |
| */ |
| public boolean isOutputParameter() { |
| return outputParameter; |
| } |
| |
| /** |
| * Close current result-set |
| * |
| * @throws SQLException if socket error occurs |
| */ |
| @Override |
| public void close() throws SQLException { |
| if (!loaded) { |
| try { |
| skipRemaining(); |
| } catch (IOException ioe) { |
| throw exceptionFactory.create("Error while streaming resultSet data", "08000", ioe); |
| } |
| } |
| this.closed = true; |
| if (closeOnCompletion) { |
| statement.close(); |
| } |
| } |
| |
| /** |
| * Closing result-set due to closing statement that issue command. |
| * |
| * @param lock thread locker object |
| * @throws SQLException if any error occurs |
| */ |
| public void closeFromStmtClose(ReentrantLock lock) throws SQLException { |
| lock.lock(); |
| try { |
| this.fetchRemaining(); |
| this.closed = true; |
| } finally { |
| lock.unlock(); |
| } |
| } |
| |
| /** Aborting result-set, without any consideration for connection state. */ |
| public void abort() { |
| this.closed = true; |
| } |
| |
| /** |
| * return current row RAW data |
| * |
| * @return current row RAW data |
| */ |
| protected byte[] getCurrentRowData() { |
| return data[0]; |
| } |
| |
| /** |
| * Add a row |
| * |
| * @param buf add row |
| */ |
| protected void addRowData(byte[] buf) { |
| if (dataSize + 1 > data.length) { |
| growDataArray(); |
| } |
| data[dataSize++] = buf; |
| } |
| |
| /** |
| * Update current row |
| * |
| * @param rawData new row |
| */ |
| protected void updateRowData(byte[] rawData) { |
| data[rowPointer] = rawData; |
| if (rawData == null) { |
| setNullRowBuf(); |
| } else { |
| setRow(rawData); |
| fieldIndex.set(-1); |
| } |
| } |
| |
| private void checkIndex(int index) throws SQLException { |
| if (index < 1 || index > maxIndex) { |
| throw new SQLException( |
| String.format("Wrong index position. Is %s but must be in 1-%s range", index, maxIndex)); |
| } |
| if (rowBuf.buf == null) { |
| throw new SQLDataException("wrong row position", "22023"); |
| } |
| } |
| |
| /** |
| * has last data getter return a null value |
| * |
| * @return true if was null |
| */ |
| @Override |
| public boolean wasNull() { |
| return rowDecoder.wasNull(nullBitmap, fieldIndex, fieldLength); |
| } |
| |
| @Override |
| public String getString(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeString(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public boolean getBoolean(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return false; |
| } |
| return rowDecoder.decodeBoolean(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public byte getByte(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0; |
| } |
| return rowDecoder.decodeByte(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public short getShort(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0; |
| } |
| return rowDecoder.decodeShort(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public int getInt(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0; |
| } |
| return rowDecoder.decodeInt(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public long getLong(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0L; |
| } |
| return rowDecoder.decodeLong(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| /** |
| * Retrieves the value of the designated column in the current row of this ResultSet object as a |
| * BigInteger. |
| * |
| * @param columnIndex index |
| * @return BigInteger value |
| * @throws SQLException if cannot be decoded as a BigInteger |
| */ |
| public BigInteger getBigInteger(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| BigIntegerCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| /** |
| * Retrieves the value of the designated column in the current row of this ResultSet object as a |
| * BigInteger. |
| * |
| * @param columnLabel column label |
| * @return BigInteger value |
| * @throws SQLException if cannot be decoded as a BigInteger |
| */ |
| public BigInteger getBigInteger(String columnLabel) throws SQLException { |
| return getBigInteger(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public float getFloat(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0F; |
| } |
| return rowDecoder.decodeFloat(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public double getDouble(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return 0D; |
| } |
| return rowDecoder.decodeDouble(metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| @Deprecated |
| public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| BigDecimal d = |
| rowDecoder.decode( |
| BigDecimalCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| if (d == null) return null; |
| return d.setScale(scale, RoundingMode.HALF_DOWN); |
| } |
| |
| @Override |
| public byte[] getBytes(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| ByteArrayCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public Date getDate(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeDate(metadataList, fieldIndex, rowBuf, fieldLength, null); |
| } |
| |
| @Override |
| public Time getTime(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeTime(metadataList, fieldIndex, rowBuf, fieldLength, null); |
| } |
| |
| @Override |
| public Timestamp getTimestamp(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeTimestamp(metadataList, fieldIndex, rowBuf, fieldLength, null); |
| } |
| |
| @Override |
| public InputStream getAsciiStream(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| StreamCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| @Deprecated |
| public InputStream getUnicodeStream(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| StreamCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public InputStream getBinaryStream(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| StreamCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public String getString(String columnLabel) throws SQLException { |
| return getString(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public boolean getBoolean(String columnLabel) throws SQLException { |
| return getBoolean(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public byte getByte(String columnLabel) throws SQLException { |
| return getByte(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public short getShort(String columnLabel) throws SQLException { |
| return getShort(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public int getInt(String columnLabel) throws SQLException { |
| return getInt(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public long getLong(String columnLabel) throws SQLException { |
| return getLong(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public float getFloat(String columnLabel) throws SQLException { |
| return getFloat(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public double getDouble(String columnLabel) throws SQLException { |
| return getDouble(findColumn(columnLabel)); |
| } |
| |
| @Override |
| @Deprecated |
| public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { |
| return getBigDecimal(findColumn(columnLabel), scale); |
| } |
| |
| @Override |
| public byte[] getBytes(String columnLabel) throws SQLException { |
| return getBytes(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Date getDate(String columnLabel) throws SQLException { |
| return getDate(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Time getTime(String columnLabel) throws SQLException { |
| return getTime(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Timestamp getTimestamp(String columnLabel) throws SQLException { |
| return getTimestamp(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public InputStream getAsciiStream(String columnLabel) throws SQLException { |
| return getAsciiStream(findColumn(columnLabel)); |
| } |
| |
| @Override |
| @Deprecated |
| public InputStream getUnicodeStream(String columnLabel) throws SQLException { |
| return getUnicodeStream(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public InputStream getBinaryStream(String columnLabel) throws SQLException { |
| return getBinaryStream(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public SQLWarning getWarnings() throws SQLException { |
| if (this.statement == null) { |
| return null; |
| } |
| return this.statement.getWarnings(); |
| } |
| |
| @Override |
| public void clearWarnings() throws SQLException { |
| if (this.statement != null) { |
| this.statement.clearWarnings(); |
| } |
| } |
| |
| @Override |
| public String getCursorName() throws SQLException { |
| throw exceptionFactory.notSupported("Cursors are not supported"); |
| } |
| |
| @Override |
| public ResultSetMetaData getMetaData() { |
| return new ResultSetMetaData(exceptionFactory, metadataList, context.getConf(), forceAlias); |
| } |
| |
| @Override |
| public Object getObject(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.defaultDecode( |
| context.getConf(), metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| @Override |
| public Object getObject(String columnLabel) throws SQLException { |
| return getObject(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Reader getCharacterStream(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| ReaderCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public Reader getCharacterStream(String columnLabel) throws SQLException { |
| return getCharacterStream(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public BigDecimal getBigDecimal(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| BigDecimalCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public BigDecimal getBigDecimal(String columnLabel) throws SQLException { |
| return getBigDecimal(findColumn(columnLabel)); |
| } |
| |
| /** |
| * Verify that result-set is not closed, throwing an exception if closed |
| * |
| * @throws SQLException if closed |
| */ |
| protected void checkClose() throws SQLException { |
| if (closed) { |
| throw exceptionFactory.create("Operation not permit on a closed resultSet", "HY000"); |
| } |
| } |
| |
| /** |
| * Throw an exception if result-set type is ResultSet.TYPE_FORWARD_ONLY |
| * |
| * @throws SQLException throw error if type is ResultSet.TYPE_FORWARD_ONLY |
| */ |
| protected void checkNotForwardOnly() throws SQLException { |
| if (resultSetType == ResultSet.TYPE_FORWARD_ONLY) { |
| throw exceptionFactory.create("Operation not permit on TYPE_FORWARD_ONLY resultSet", "HY000"); |
| } |
| } |
| |
| @Override |
| public boolean isBeforeFirst() throws SQLException { |
| checkClose(); |
| return rowPointer == -1 && dataSize > 0; |
| } |
| |
| @Override |
| public abstract boolean isAfterLast() throws SQLException; |
| |
| @Override |
| public abstract boolean isFirst() throws SQLException; |
| |
| @Override |
| public abstract boolean isLast() throws SQLException; |
| |
| @Override |
| public abstract void beforeFirst() throws SQLException; |
| |
| @Override |
| public abstract void afterLast() throws SQLException; |
| |
| @Override |
| public abstract boolean first() throws SQLException; |
| |
| @Override |
| public abstract boolean last() throws SQLException; |
| |
| @Override |
| public abstract int getRow() throws SQLException; |
| |
| @Override |
| public abstract boolean absolute(int row) throws SQLException; |
| |
| @Override |
| public abstract boolean relative(int rows) throws SQLException; |
| |
| @Override |
| public abstract boolean previous() throws SQLException; |
| |
| @Override |
| public int getFetchDirection() { |
| return FETCH_UNKNOWN; |
| } |
| |
| @Override |
| public void setFetchDirection(int direction) throws SQLException { |
| if (direction == FETCH_REVERSE) { |
| throw exceptionFactory.create( |
| "Invalid operation. Allowed direction are ResultSet.FETCH_FORWARD and" |
| + " ResultSet.FETCH_UNKNOWN"); |
| } |
| } |
| |
| @Override |
| public int getType() { |
| return resultSetType; |
| } |
| |
| @Override |
| public int getConcurrency() { |
| return CONCUR_READ_ONLY; |
| } |
| |
| @Override |
| public boolean rowUpdated() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public boolean rowInserted() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public boolean rowDeleted() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNull(int columnIndex) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBoolean(int columnIndex, boolean x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateByte(int columnIndex, byte x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateShort(int columnIndex, short x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateInt(int columnIndex, int x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateLong(int columnIndex, long x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateFloat(int columnIndex, float x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateDouble(int columnIndex, double x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateString(int columnIndex, String x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBytes(int columnIndex, byte[] x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateDate(int columnIndex, Date x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateTime(int columnIndex, Time x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(int columnIndex, Object x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNull(String columnLabel) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBoolean(String columnLabel, boolean x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateByte(String columnLabel, byte x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateShort(String columnLabel, short x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateInt(String columnLabel, int x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateLong(String columnLabel, long x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateFloat(String columnLabel, float x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateDouble(String columnLabel, double x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateString(String columnLabel, String x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBytes(String columnLabel, byte[] x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateDate(String columnLabel, Date x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateTime(String columnLabel, Time x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(String columnLabel, InputStream x, int length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(String columnLabel, Reader reader, int length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(String columnLabel, Object x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void insertRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void deleteRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void refreshRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void cancelRowUpdates() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void moveToInsertRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void moveToCurrentRow() throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public Statement getStatement() { |
| return statement; |
| } |
| |
| /** |
| * Update statement that initiate this result-set |
| * |
| * @param stmt statement |
| */ |
| public void setStatement(Statement stmt) { |
| statement = stmt; |
| } |
| |
| /** Force using alias as name */ |
| public void useAliasAsName() { |
| for (Column packet : metadataList) { |
| packet.useAliasAsName(); |
| } |
| forceAlias = true; |
| } |
| |
| @Override |
| public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException { |
| if (map == null || map.isEmpty()) { |
| return getObject(columnIndex); |
| } |
| throw exceptionFactory.notSupported( |
| "Method ResultSet.getObject(int columnIndex, Map<String, Class<?>> map) not supported for" |
| + " non empty map"); |
| } |
| |
| @Override |
| public Ref getRef(int columnIndex) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getRef not supported"); |
| } |
| |
| @Override |
| public Blob getBlob(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| BlobCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public Clob getClob(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| ClobCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public Array getArray(int columnIndex) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getArray not supported"); |
| } |
| |
| @Override |
| public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException { |
| if (map == null || map.isEmpty()) { |
| return getObject(columnLabel); |
| } |
| throw exceptionFactory.notSupported( |
| "Method ResultSet.getObject(String columnLabel, Map<String, Class<?>> map) not supported"); |
| } |
| |
| @Override |
| public Ref getRef(String columnLabel) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getRef not supported"); |
| } |
| |
| @Override |
| public Blob getBlob(String columnLabel) throws SQLException { |
| return getBlob(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Clob getClob(String columnLabel) throws SQLException { |
| return getClob(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public Array getArray(String columnLabel) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getArray not supported"); |
| } |
| |
| @Override |
| public Date getDate(int columnIndex, Calendar cal) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeDate(metadataList, fieldIndex, rowBuf, fieldLength, cal); |
| } |
| |
| @Override |
| public Date getDate(String columnLabel, Calendar cal) throws SQLException { |
| return getDate(findColumn(columnLabel), cal); |
| } |
| |
| @Override |
| public Time getTime(int columnIndex, Calendar cal) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeTime(metadataList, fieldIndex, rowBuf, fieldLength, cal); |
| } |
| |
| @Override |
| public Time getTime(String columnLabel, Calendar cal) throws SQLException { |
| return getTime(findColumn(columnLabel), cal); |
| } |
| |
| @Override |
| public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decodeTimestamp(metadataList, fieldIndex, rowBuf, fieldLength, cal); |
| } |
| |
| @Override |
| public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { |
| return getTimestamp(findColumn(columnLabel), cal); |
| } |
| |
| @Override |
| public URL getURL(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| |
| String s = |
| rowDecoder.decode( |
| StringCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| if (s == null) return null; |
| try { |
| return new URL(s); |
| } catch (MalformedURLException e) { |
| throw exceptionFactory.create(String.format("Could not parse '%s' as URL", s)); |
| } |
| } |
| |
| @Override |
| public URL getURL(String columnLabel) throws SQLException { |
| return getURL(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public void updateRef(int columnIndex, Ref x) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.updateRef not supported"); |
| } |
| |
| @Override |
| public void updateRef(String columnLabel, Ref x) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.updateRef not supported"); |
| } |
| |
| @Override |
| public void updateBlob(int columnIndex, Blob x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBlob(String columnLabel, Blob x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(int columnIndex, Clob x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(String columnLabel, Clob x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateArray(int columnIndex, Array x) throws SQLException { |
| throw exceptionFactory.notSupported("Array are not supported"); |
| } |
| |
| @Override |
| public void updateArray(String columnLabel, Array x) throws SQLException { |
| throw exceptionFactory.notSupported("Array are not supported"); |
| } |
| |
| @Override |
| public RowId getRowId(int columnIndex) throws SQLException { |
| throw exceptionFactory.notSupported("RowId are not supported"); |
| } |
| |
| @Override |
| public RowId getRowId(String columnLabel) throws SQLException { |
| throw exceptionFactory.notSupported("RowId are not supported"); |
| } |
| |
| @Override |
| public void updateRowId(int columnIndex, RowId x) throws SQLException { |
| throw exceptionFactory.notSupported("RowId are not supported"); |
| } |
| |
| @Override |
| public void updateRowId(String columnLabel, RowId x) throws SQLException { |
| throw exceptionFactory.notSupported("RowId are not supported"); |
| } |
| |
| @Override |
| public int getHoldability() { |
| return ResultSet.HOLD_CURSORS_OVER_COMMIT; |
| } |
| |
| @Override |
| public boolean isClosed() { |
| return closed; |
| } |
| |
| @Override |
| public void updateNString(int columnIndex, String nString) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNString(String columnLabel, String nString) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(int columnIndex, NClob nClob) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(String columnLabel, NClob nClob) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public NClob getNClob(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return (NClob) |
| rowDecoder.decode(ClobCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public NClob getNClob(String columnLabel) throws SQLException { |
| return getNClob(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public SQLXML getSQLXML(int columnIndex) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getSQLXML not supported"); |
| } |
| |
| @Override |
| public SQLXML getSQLXML(String columnLabel) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.getSQLXML not supported"); |
| } |
| |
| @Override |
| public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.updateSQLXML not supported"); |
| } |
| |
| @Override |
| public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { |
| throw exceptionFactory.notSupported("Method ResultSet.updateSQLXML not supported"); |
| } |
| |
| @Override |
| public String getNString(int columnIndex) throws SQLException { |
| return getString(columnIndex); |
| } |
| |
| @Override |
| public String getNString(String columnLabel) throws SQLException { |
| return getString(columnLabel); |
| } |
| |
| @Override |
| public Reader getNCharacterStream(int columnIndex) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| if (fieldLength == NULL_LENGTH) { |
| return null; |
| } |
| return rowDecoder.decode( |
| ReaderCodec.INSTANCE, null, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| |
| @Override |
| public Reader getNCharacterStream(String columnLabel) throws SQLException { |
| return getNCharacterStream(findColumn(columnLabel)); |
| } |
| |
| @Override |
| public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNCharacterStream(String columnLabel, Reader reader, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(String columnLabel, InputStream x, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(String columnLabel, InputStream x, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(String columnLabel, Reader reader, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBlob(int columnIndex, InputStream inputStream, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBlob(String columnLabel, InputStream inputStream, long length) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(int columnIndex, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateClob(String columnLabel, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(int columnIndex, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateNClob(String columnLabel, Reader reader) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public <T> T getObject(int columnIndex, Class<T> type) throws SQLException { |
| checkIndex(columnIndex); |
| fieldLength = |
| rowDecoder.setPosition( |
| columnIndex - 1, fieldIndex, maxIndex, rowBuf, nullBitmap, metadataList); |
| Calendar calendar = null; |
| if (wasNull()) { |
| if (type.isPrimitive()) { |
| throw new SQLException( |
| String.format("Cannot return null for primitive %s", type.getName())); |
| } |
| return null; |
| } |
| Configuration conf = context.getConf(); |
| ColumnDecoder column = metadataList[columnIndex - 1]; |
| // type generic, return "natural" java type |
| if (Object.class.equals(type) || type == null) { |
| return (T) rowDecoder.defaultDecode(conf, metadataList, fieldIndex, rowBuf, fieldLength); |
| } |
| |
| for (Codec<?> codec : conf.codecs()) { |
| if (codec.canDecode(column, type)) { |
| return rowDecoder.decode( |
| (Codec<T>) codec, calendar, rowBuf, fieldLength, metadataList, fieldIndex); |
| } |
| } |
| rowBuf.skip(fieldLength); |
| throw new SQLException( |
| String.format("Type %s not supported type for %s type", type, column.getType().name())); |
| } |
| |
| @Override |
| public <T> T getObject(String columnLabel, Class<T> type) throws SQLException { |
| return getObject(findColumn(columnLabel), type); |
| } |
| |
| @Override |
| public <T> T unwrap(Class<T> iface) throws SQLException { |
| if (isWrapperFor(iface)) { |
| return iface.cast(this); |
| } |
| throw new SQLException("The receiver is not a wrapper for " + iface.getName()); |
| } |
| |
| @Override |
| public boolean isWrapperFor(Class<?> iface) { |
| return iface.isInstance(this); |
| } |
| |
| @Override |
| public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| @Override |
| public void updateObject(String columnLabel, Object x, SQLType targetSqlType) |
| throws SQLException { |
| throw exceptionFactory.notSupported("Not supported when using CONCUR_READ_ONLY concurrency"); |
| } |
| |
| /** Set row buffer to null (no row) */ |
| protected void setNullRowBuf() { |
| rowBuf.buf(null, 0, 0); |
| } |
| |
| /** |
| * set row decoder to current row data |
| * |
| * @param row row |
| */ |
| public void setRow(byte[] row) { |
| rowBuf.buf(row, row.length, 0); |
| fieldIndex.set(-1); |
| } |
| |
| public int findColumn(String label) throws SQLException { |
| if (label == null) throw new SQLException("null is not a valid label value"); |
| if (mapper == null) { |
| mapper = new HashMap<>(); |
| for (int i = 0; i < maxIndex; i++) { |
| Column ci = metadataList[i]; |
| String columnAlias = ci.getColumnAlias(); |
| if (columnAlias != null) { |
| columnAlias = columnAlias.toLowerCase(Locale.ROOT); |
| mapper.putIfAbsent(columnAlias, i + 1); |
| String tableAlias = ci.getTableAlias(); |
| String tableLabel = tableAlias != null ? tableAlias : ci.getTable(); |
| mapper.putIfAbsent(tableLabel.toLowerCase(Locale.ROOT) + "." + columnAlias, i + 1); |
| } |
| } |
| } |
| Integer ind = mapper.get(label.toLowerCase(Locale.ROOT)); |
| if (ind == null) { |
| String keys = Arrays.toString(mapper.keySet().toArray(new String[0])); |
| throw new SQLException(String.format("Unknown label '%s'. Possible value %s", label, keys)); |
| } |
| return ind; |
| } |
| } |