Mercurial > hg > monetdb-java
view src/main/java/nl/cwi/monetdb/jdbc/MonetResultSet.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 | e026fe73bb5e |
children | 92bac8379d06 |
line wrap: on
line source
/* * 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 1997 - July 2008 CWI, August 2008 - 2017 MonetDB B.V. */ package nl.cwi.monetdb.jdbc; import nl.cwi.monetdb.mcl.protocol.ProtocolException; import nl.cwi.monetdb.mcl.responses.AbstractDataBlockResponse; import nl.cwi.monetdb.mcl.responses.ResultSetResponse; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.*; import java.util.Calendar; import java.util.Map; import java.util.UUID; /** * A ResultSet suitable for the MonetDB database. * * A table of data representing a database result set, which is usually * generated by executing a statement that queries the database. * * A ResultSet object maintains a cursor pointing to its current row of data. * Initially the cursor is positioned before the first row. The next method * moves the cursor to the next row, and because it returns false when there * are no more rows in the ResultSet object, it can be used in a while loop to * iterate through the result set. * * The current state of this ResultSet is that it supports positioning in the * result set, absolute and relative. A slight performance difference between * FORWARD_ONLY or result sets scrollable in both directions can be noticed as * for FORWARD_ONLY result sets the memory usage will be likely lower for large * result sets. * * @author Fabian Groffen, Martin van Dinther, Pedro Ferreira * @version 0.8 */ public class MonetResultSet extends MonetWrapper implements ResultSet { /** The current position of the cursor for this ResultSet object */ int curRow = 0; // a blank final is immutable once assigned in the constructor /** A Header to retrieve lines from */ private final ResultSetResponse header; /** The names of the columns in this ResultSet */ private final String[] columns; /** The MonetDB types of the columns in this ResultSet */ private final String[] types; /** The JDBC SQL types of the columns in this ResultSet. The content will be derived from the MonetDB types[] */ private final int[] JdbcSQLTypes; /** The number of rows in this ResultSet */ final int tupleCount; /** The parental Statement object */ private final Statement statement; /** The type of this ResultSet (forward or scrollable) */ private int type = TYPE_FORWARD_ONLY; /** The concurrency of this ResultSet (currently only read-only) */ private int concurrency = CONCUR_READ_ONLY; /** The warnings for this ResultSet object */ private SQLWarning warnings; /** Just a dummy variable to keep store the fetchsize set. */ private int fetchSize; /** The current row's values */ private AbstractDataBlockResponse currentBlock; /** * Main constructor backed by the given Header. * * @param statement the statement which created this ResultSet * @param header a header containing the query, resultset type, etc. * @throws SQLException is a protocol error occurs */ MonetResultSet(Statement statement, ResultSetResponse header) throws SQLException { if (statement == null) { throw new IllegalArgumentException("Statement may not be null!"); } if (header == null) { throw new IllegalArgumentException("ResultSetResponse may not be null!"); } this.statement = statement; 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 */ 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 this.tupleCount = header.getTuplecount(); this.columns = header.getNames(); this.types = header.getTypes(); this.JdbcSQLTypes = header.getJdbcSQLTypes(); } /** * Constructor used by MonetVirtualResultSet. * DO NOT USE THIS CONSTRUCTOR IF YOU ARE NOT EXTENDING THIS OBJECT! * * @param statement the statement which created this ResultSet * @param columns the column names * @param types the column types * @param results the number of rows in the ResultSet * @throws IllegalArgumentException if communicating with monet failed */ MonetResultSet(Statement statement, String[] columns, String[] types, int[] JdbcSQLTypes, int results) throws IllegalArgumentException { if (statement == null) { throw new IllegalArgumentException("Statement may not be null!"); } if (columns == null || types == null) { throw new IllegalArgumentException("One of the given arguments is null!"); } if (columns.length != types.length) { throw new IllegalArgumentException("Given arguments are not the same size!"); } if (results < 0) { throw new IllegalArgumentException("Negative rowcount not allowed!"); } this.statement = statement; this.header = null; this.fetchSize = 0; this.tupleCount = results; this.columns = columns; this.types = types; this.JdbcSQLTypes = JdbcSQLTypes; } //== 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. * * If the row number is positive, the cursor moves to the given row number with respect to the beginning of the * result set. The first row is row 1, the second is row 2, and so on. * * If the given row number is negative, the cursor moves to an absolute row position with respect to the end of the * result set. For example, calling the method absolute(-1) positions the cursor on the last row; calling the * method absolute(-2) moves the cursor to the next-to-last row, and so on. * * 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(). * * @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 */ @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 (header.isClosed()) throw new SQLException("ResultSet is closed!", "M1M20"); // first calculate what the JDBC row is if (row < 0) { // calculate the negatives... 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 } // store it this.curRow = row; this.currentBlock = header.getDataBlockCorrespondingToLine(row - 1); return this.curRow <= this.tupleCount; } /** * 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 */ @Override public void afterLast() throws SQLException { absolute(tupleCount + 1); } /** * 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 */ @Override public void beforeFirst() throws SQLException { absolute(0); } /** * 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() { warnings = null; } /** * 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() { if (header != null && !header.isClosed()) { header.close(); } if (statement instanceof MonetStatement) { ((MonetStatement)statement).closeIfCompletion(); } } // 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 * column will be returned. * * @param columnName the name of the column * @return the column index of the given column name * @throws SQLException if the ResultSet object does not contain columnName */ @Override public int findColumn(String columnName) throws SQLException { if (columnName != null) { final int array_size = columns.length; for (int i = 0; i < array_size; i++) { if (columnName.equals(columns[i])) return i + 1; } /* if an exact match did not succeed try a case insensitive match */ for (int i = 0; i < array_size; i++) { if (columnName.equalsIgnoreCase(columns[i])) return i + 1; } } throw new SQLException("No such column name: " + columnName, "M1M05"); } /** * 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 */ @Override public boolean first() throws SQLException { return absolute(1); } @Override public Array getArray(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("getArray"); } @Override public Array getArray(String colName) throws SQLException { throw newSQLFeatureNotSupportedException("getArray"); } @Override public InputStream getAsciiStream(int columnIndex) throws SQLException { try { InputStream res = null; switch (JdbcSQLTypes[columnIndex - 1]) { case Types.CLOB: Clob cl = getClob(columnIndex); if(cl != null) { res = cl.getAsciiStream(); } break; case Types.BLOB: case Types.LONGVARBINARY: case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: byte[] bytes = getBytes(columnIndex); if(bytes != null) { res = new ByteArrayInputStream(getBytes(columnIndex)); } break; default: throw new SQLException("Conversion from " + types[columnIndex - 1] + " to ascii stream not supported", "M1M05"); } return res; } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } @Override public InputStream getAsciiStream(String columnName) throws SQLException { return getAsciiStream(findColumn(columnName)); } @Override @Deprecated public InputStream getUnicodeStream(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("getUnicodeStream"); } @Override @Deprecated public InputStream getUnicodeStream(String columnName) throws SQLException { throw newSQLFeatureNotSupportedException("getUnicodeStream"); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a stream of * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable * for retrieving large LONGVARBINARY values. * <br/><br/> * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method * InputStream.available is called whether there is data available or not. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the * value is SQL NULL, the value returned is null * @throws SQLException if the columnIndex is not valid; if a database access error occurs or this method is called * on a closed result set */ @Override public InputStream getBinaryStream(int columnIndex) throws SQLException { try { InputStream res = null; switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BLOB: Blob cl = getBlob(columnIndex); if(cl != null) { res = cl.getBinaryStream(); } break; case Types.LONGVARBINARY: byte[] bytes = getBytes(columnIndex); if(bytes != null) { res = new ByteArrayInputStream(getBytes(columnIndex)); } break; default: throw new SQLException("Conversion from " + types[columnIndex - 1] + " to binary stream not supported", "M1M05"); } return res; } 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 stream of * uninterpreted bytes. The value can then be read in chunks from the stream. This method is particularly suitable * for retrieving large LONGVARBINARY values. * <br/><br/> * Note: All the data in the returned stream must be read prior to getting the value of any other column. The next * call to a getter method implicitly closes the stream. Also, a stream may return 0 when the method available is * called whether there is data available or not. * * @param columnName 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 Java input stream that delivers the database column value as a stream of uninterpreted bytes; if the * value is SQL NULL, the result is null * @throws SQLException if the columnLabel is not valid; if a database access error occurs or this method is called * on a closed result set */ @Override public InputStream getBinaryStream(String columnName) throws SQLException { return getBinaryStream(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader * 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. * @throws SQLException if a database access error occurs */ @Override public Reader getCharacterStream(int columnIndex) throws SQLException { try { String ss = currentBlock.getValueAsString(columnIndex - 1); return (ss == null) ? null : new StringReader(ss); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader * object. * * @param columnName the name of the column * @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 public Reader getCharacterStream(String columnName) throws SQLException { return getCharacterStream(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns. * * @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. * @throws SQLException if a database access error occurs * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public Reader getNCharacterStream(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("getNCharacterStream"); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a java.io.Reader * object. It is intended for use when accessing NCHAR, NVARCHAR and LONGNVARCHAR columns. * * @param columnName the name of the column * @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 * @throws SQLFeatureNotSupportedException the JDBC driver does * not support this method */ @Override public Reader getNCharacterStream(String columnName) throws SQLException { throw newSQLFeatureNotSupportedException("getNCharacterStream"); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a Blob object in * the Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Blob object representing the SQL BLOB value in the specified column * @throws SQLException if a database access error occurs */ @Override public Blob getBlob(int columnIndex) throws SQLException { try { return (MonetBlob) currentBlock.getObjectValue(columnIndex - 1); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a Blob object in the * Java programming language. * * @param colName the name of the column from which to retrieve the value * @return a Blob object representing the SQL BLOB value in the specified column * @throws SQLException if a database access error occurs */ @Override public Blob getBlob(String colName) throws SQLException { return getBlob(findColumn(colName)); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a Clob object in the * Java programming language. * * @param columnIndex the first column is 1, the second is 2, ... * @return a Clob object representing the SQL CLOB value in the specified column * @throws SQLException if a database access error occurs */ @Override public Clob getClob(int columnIndex) throws SQLException { try { return (MonetClob) currentBlock.getObjectValue(columnIndex - 1); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a Clob object in the * Java programming language. * * @param colName the name of the column from which to retrieve the value * @return a Clob object representing the SQL CLOB value in the specified column * @throws SQLException if a database access error occurs */ @Override public Clob getClob(String colName) throws SQLException { return getClob(findColumn(colName)); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a NClob object in the * Java programming language. * * @param i the first column is 1, the second is 2, ... * @return a NClob object representing the SQL NCLOB value in the specified column * @throws SQLException if a database access error occurs * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public NClob getNClob(int i) throws SQLException { throw newSQLFeatureNotSupportedException("getNClob"); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a NClob object in the * Java programming language. * * @param colName the name of the column from which to retrieve the value * @return a NClob object representing the SQL NCLOB value in the specified column * @throws SQLException if a database access error occurs * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public NClob getNClob(String colName) throws SQLException { throw newSQLFeatureNotSupportedException("getNClob"); } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a java.math.BigDecimal with full precision. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value (full precision); 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 BigDecimal getBigDecimal(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.NUMERIC: case Types.DECIMAL: return (BigDecimal) currentBlock.getObjectValue(columnIndex - 1); case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(bol ? 1 : 0); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(bb); case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(sh); case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(in); case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(lon); case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(floa); case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? null : new BigDecimal(dou); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return (ss == null) ? null : new BigDecimal(ss); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to boolean type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a java.math.BigDecimal with full precision. * * @param columnIndex the first column is 1, the second is 2, ... * @param scale the number of digits to the right of the decimal point * @return the column value (full precision); 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 @Deprecated public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { try { BigDecimal val = getBigDecimal(columnIndex); if(val != null) { val.setScale(scale); } 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.math.BigDecimal with full precision. * * @param columnName the SQL name of the column * @return the column value (full precision); 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 BigDecimal getBigDecimal(String columnName) throws SQLException { return getBigDecimal(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a java.math.BigDecimal with full precision. * * @param columnName the SQL name of the column * @param scale the number of digits to the right of the decimal point * @return the column value (full precision); 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 @Deprecated public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException { return getBigDecimal(findColumn(columnName), scale); } // See Sun JDBC Specification 3.0 Table B-6 /** * Retrieves the value of the designated column in the current row of this ResultSet object as a boolean 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 false * @throws SQLException if there is no such column */ @Override public boolean getBoolean(int columnIndex) throws SQLException { try { // match type specific values switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && bol; case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && bb != 0; case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && sh != 0; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && in != 0; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && lon != 0; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && floa != 0.0f; case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return !currentBlock.isLastReadWasNull() && dou != 0.0d; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String val = currentBlock.getValueAsString(columnIndex - 1); return val != null && !"0".equals(val) && ("1".equals(val) || Boolean.parseBoolean(val)); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec != null && bigdec.compareTo(BigDecimal.ZERO) != 0; default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to boolean type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a boolean 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 false * @throws SQLException if the ResultSet object does not contain columnName */ @Override public boolean getBoolean(String columnName) throws SQLException { return getBoolean(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a byte 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 * @throws SQLException if a database access error occurs */ @Override public byte getByte(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : bb; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (bol ? (byte) 1 : (byte) 0); case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (byte) sh; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (byte) in; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (byte) lon; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (byte) Math.round(floa); case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (byte) Math.round(dou); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0 : Byte.parseByte(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0 : bigdec.byteValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to byte type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a byte 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 * @throws SQLException if a database access error occurs */ @Override public byte getByte(String columnName) throws SQLException { return getByte(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a byte array in the Java programming language. The * 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 * @throws SQLException if a database access error occurs */ @Override public byte[] getBytes(int columnIndex) throws SQLException { try { // According to Table B-6, getBytes() only operates on BINARY types switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BLOB: MonetBlob mb = (MonetBlob) currentBlock.getObjectValue(columnIndex - 1); return mb == null ? null : mb.getBuffer(); case Types.LONGVARBINARY: // unpack the HEX (BLOB) notation to real bytes return (byte[]) currentBlock.getObjectValue(columnIndex - 1); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? null : ss.getBytes(); default: throw new SQLException("Cannot operate on " + types[columnIndex - 1] + " type", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a byte array in the * Java programming language. The bytes represent the raw values returned by the driver. * * @param columnName the SQL name of the column * @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 byte[] getBytes(String columnName) throws SQLException { return getBytes(findColumn(columnName)); } /** * Retrieves the concurrency mode of this ResultSet object. The concurrency used is determined by the Statement * object that created the result set. * * NOTE: MonetDB only supports read-only result sets, and will always return ResultSet.CONCUR_READ_ONLY * * @return the concurrency type, either ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE */ @Override public int getConcurrency() { return concurrency; } /** * Retrieves the name of the SQL cursor used by this ResultSet object. * In SQL, a result table is retrieved through a cursor that is named. * For MonetDB this is the header.id returned in a resultset header. The * current row of a result set can be updated or deleted using a positioned * update/delete statement that references the cursor name. To insure that * the cursor has the proper isolation level to support update, the * cursor's SELECT statement should be of the form SELECT FOR UPDATE. If * FOR UPDATE is omitted, the positioned updates may fail. * * The JDBC API supports this SQL feature by providing the name of the SQL * cursor used by a ResultSet object. The current row of a ResultSet object * is also the current row of this SQL cursor. * * Note: If positioned update is not supported, a SQLException is thrown. MonetDB currently doesn't support updates, * so the SQLException is thrown for now. * * @return the SQL name for this ResultSet object's cursor * @throws SQLException if a database access error occurs */ @Override public String getCursorName() throws SQLException { throw new SQLException("Positioned updates not supported for this " + "cursor (" + (header != null ? header.getId() : "") + ")", "0AM21"); } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a double 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 * @throws SQLException if there is no such column */ @Override public double getDouble(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.DOUBLE: double res = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : res; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : (bol ? 1.0d : 0.0d); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : (double) bb; case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : (double) sh; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : (double) in; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : (double) lon; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0d : floa; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0.0d : Double.parseDouble(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0.0d : bigdec.doubleValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to double type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a double 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 * @throws SQLException if the ResultSet object does not contain columnName */ @Override public double getDouble(String columnName) throws SQLException { return getDouble(findColumn(columnName)); } /** * Retrieves the holdability of this ResultSet object. * * @return either ResultSet.HOLD_CURSORS_OVER_COMMIT or ResultSet.CLOSE_CURSORS_AT_COMMIT * @throws SQLException if a database access error occurs */ @Override public int getHoldability() throws SQLException { return getStatement().getConnection().getHoldability(); } /** * Retrieves the fetch direction for this ResultSet object. * <b>currently not implemented</b> * * @return the current fetch direction for this ResultSet object */ @Override public int getFetchDirection() { return ResultSet.FETCH_FORWARD; } /** * Gives a hint as to the direction in which the rows in this ResultSet * object will be processed. The initial value is determined by the * Statement object that produced this ResultSet object. * The fetch direction may be changed at any time. * <b>currently not implemented</b> * * @param direction - an int specifying the suggested fetch direction; * one of ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or ResultSet.FETCH_UNKNOWN */ @Override public void setFetchDirection(int direction) throws SQLException { switch (direction) { case ResultSet.FETCH_FORWARD: break; case ResultSet.FETCH_REVERSE: case ResultSet.FETCH_UNKNOWN: throw new SQLException("Not supported direction " + direction, "0A000"); default: throw new SQLException("Illegal direction: " + direction, "M1M05"); } } /** * Retrieves the fetch size for this ResultSet object. * * @return the current fetch size for this ResultSet object * @throws SQLException if a database access error occurs */ @Override public int getFetchSize() throws SQLException { return fetchSize; } /** * Gives the JDBC driver a hint as to the number of rows that should be * fetched from the database when more rows are needed. In MonetDB, this is * actually a no-op, because even before a MonetResultSet object is * created, the fetch size is already determined in the * MonetConnection.ResultSetResponse passed to its constructor. Since all * data blocks for this whole result set are already allocated in * MonetConnection.ResultSetResponse, it is too complicated and error-prone * to still change the fetchSize here. If one really needs to overwrite * the default fetchSize, please use MonetStatement.setFetchSize() instead. * * @param rows the number of rows to fetch * @throws SQLException if the condition 0 <= rows is not satisfied */ @Override public void setFetchSize(int rows) throws SQLException { if (rows >= 0) { fetchSize = rows; } else { throw new SQLException("Illegal fetch size value: " + rows, "M1M05"); } } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as a float 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 * @throws SQLException if there is no such column */ @Override public float getFloat(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.REAL: float res = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : res; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (bol ? 1.0f : 0.0f); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (float) bb; case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (float) sh; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (float) in; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (float) lon; case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0.0f : (float) dou; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0.0f : Float.parseFloat(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0.0f : bigdec.floatValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to float type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * 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 * @throws SQLException if the ResultSet object does not contain columnName */ @Override public float getFloat(String columnName) throws SQLException { return getFloat(findColumn(columnName)); } /** * 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 * @throws SQLException if there is no such column */ @Override public int getInt(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.INTEGER: int res = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : res; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (bol ? 1 : 0); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : bb; case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : sh; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (int) lon; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : Math.round(floa); case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (int) Math.round(dou); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0 : Integer.parseInt(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0 : bigdec.intValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to integer type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * 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 * @throws SQLException if the ResultSet object does not contain columnName */ @Override public int getInt(String columnName) throws SQLException { return getInt(findColumn(columnName)); } /** * 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 * @throws SQLException if there is no such column */ @Override public long getLong(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.BIGINT: long res = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : res; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (bol ? 1 : 0); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : bb; case Types.SMALLINT: short sh = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : sh; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : in; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : Math.round(floa); case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : Math.round(dou); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0 : Long.parseLong(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0 : bigdec.longValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to long type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(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. * * @param columnName the SQL name of the column * @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 public long getLong(String columnName) throws SQLException { return getLong(findColumn(columnName)); } /* 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. * * @return the description of this ResultSet object's columns */ @Override public ResultSetMetaData getMetaData() { // return inner class which implements the ResultSetMetaData interface return new rsmdw() { // for the more expensive methods (getPrecision(), getScale(), isNullable()), we provide a simple cache // caches to store precision, scale and isNullable values from getColumns() final int array_size = columns.length + 1; // add 1 as in JDBC columns start from 1 (array from 0). private boolean[] _is_fetched = new boolean[array_size]; private int[] _precision = new int[array_size]; private int[] _scale = new int[array_size]; private int[] _isNullable = new int[array_size]; private boolean[] _isAutoincrement = new boolean[array_size]; private Connection conn = null; private DatabaseMetaData dbmd = null; /** * A private method to fetch the precision, scale, isNullable and isAutoincrement value for a fully qualified column. * As md.getColumns() is an expensive method we call it only once per column * and cache the precision, scale, isNullable and isAutoincrement values in the above array chaches. * Also we only call md.getColumns() when we have a non empty schema name and table name and column name. */ private void fetchColumnInfo(int column) throws SQLException { if (column <= 0 || column > columns.length) throw newSQLInvalidColumnIndexException(column); _is_fetched[column] = true; _precision[column] = 0; _scale[column] = 0; _isNullable[column] = columnNullableUnknown; _isAutoincrement[column] = false; // we can only call dbmd.getColumns() when we have a specific schema name and table name and column name String schName = getSchemaName(column); if (schName != null && !schName.isEmpty()) { String tblName = getTableName(column); if (tblName != null && !tblName.isEmpty()) { String colName = getColumnName(column); if (colName != null && !colName.isEmpty()) { if (conn == null) { // first time, get a Connection object and cache it for all next columns conn = getStatement().getConnection(); } if (conn != null && dbmd == null) { // first time, get a MetaData object and cache it for all next columns dbmd = conn.getMetaData(); } if (dbmd != null) { // for precision, scale, isNullable and isAutoincrement we query the information from data dictionary ResultSet colInfo = dbmd.getColumns(null, schName, tblName, colName); if (colInfo != null) { // we expect exactly one row in the resultset if (colInfo.next()) { _precision[column] = colInfo.getInt(7); // col 7 is "COLUMN_SIZE" _scale[column] = colInfo.getInt(9); // col 9 is "DECIMAL_DIGITS" _isNullable[column] = colInfo.getInt(11); // col 11 is "NULLABLE" String strVal = colInfo.getString(23); // col 23 is "IS_AUTOINCREMENT" if (strVal != null && "YES".equals(strVal)) _isAutoincrement[column] = true; } colInfo.close(); // close the resultset to release resources } } } } } } /** * Returns the number of columns in this ResultSet object. * * @return the number of columns */ @Override public int getColumnCount() { return columns.length; } /** * Indicates whether the designated column is automatically numbered. * * @param column the first column is 1, the second is 2, ... * @return true if so; false otherwise * @throws SQLException if a database access error occurs */ @Override public boolean isAutoIncrement(int column) throws SQLException { try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _isAutoincrement[column]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Indicates whether a column's case matters. * * @param column the first column is 1, the second is 2, ... * @return true for all character string columns else false */ @Override public boolean isCaseSensitive(int column) throws SQLException { switch (getColumnType(column)) { case Types.CLOB: case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return true; default: return false; } } /** * Indicates whether the designated column can be used in a * where clause. * It is unknown to me what kind ot columns they regard to, * as I think all columns are useable in a where clause. * Returning true for all here, for the time being. * Possible thought; maybe they want to know here if it's a * real column existing in a table or not... * * @param column the first column is 1, the second is 2, ... * @return true */ @Override public boolean isSearchable(int column) { return true; } /** * Indicates whether the designated column is a cash value. * From the MonetDB database perspective it is by definition * unknown whether the value is a currency, because there are * no currency datatypes such as MONEY. With this knowledge * we can always return false here. * * @param column the first column is 1, the second is 2, ... * @return false */ @Override public boolean isCurrency(int column) { return false; } /** * Indicates whether values in the designated column are signed numbers. * Within MonetDB all numeric types (except oid and ptr) are signed. * * @param column the first column is 1, the second is 2, ... * @return true if so; false otherwise */ @Override public boolean isSigned(int column) throws SQLException { switch (getColumnType(column)) { case Types.TINYINT: case Types.SMALLINT: case Types.INTEGER: case Types.REAL: case Types.DOUBLE: case Types.BIGINT: case Types.NUMERIC: case Types.DECIMAL: return true; default: return false; } } /** * Indicates the designated column's normal maximum width in characters. * * @param column the first column is 1, the second is 2, ... * @return the normal maximum number of characters allowed as the width of the designated column * @throws SQLException if there is no such column */ @Override public int getColumnDisplaySize(int column) throws SQLException { int ret = 1; if (header != null) { try { ret = header.getColumnLengths()[column - 1]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } return ret; } /** * Get the designated column's schema name. * * @param column the first column is 1, the second is 2, ... * @return schema name or "" if not applicable * @throws SQLException if a database access error occurs */ @Override public String getSchemaName(int column) throws SQLException { if (header != null) { // figure the name out try { String schema = header.getTableNames()[column - 1]; if (schema != null) { int dot = schema.indexOf('.'); return (dot >= 0) ? schema.substring(0, dot) : ""; } } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } return ""; } /** * Gets the designated column's table name. * * @param column the first column is 1, the second is 2, ... * @return table name or "" if not applicable */ @Override public String getTableName(int column) throws SQLException { if (header != null) { // figure the name out try { String table = header.getTableNames()[column - 1]; if (table != null) { int dot = table.indexOf('.'); return (dot >= 0) ? table.substring(dot + 1) : table; } } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } return ""; } /** * Get the designated column's number of decimal digits. This method is currently very expensive as it needs * to retrieve the information from the database using an SQL query. * * @param column the first column is 1, the second is 2, ... * @return precision * @throws SQLException if a database access error occurs */ @Override public int getPrecision(int column) throws SQLException { try { if (!_is_fetched[column]) { fetchColumnInfo(column); } if (_precision[column] == 0) { // apparently no precision could be fetched use columnDisplaySize() value for variable // length data types switch (getColumnType(column)) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.LONGVARBINARY: case Types.BLOB: case Types.NUMERIC: case Types.DECIMAL: _precision[column] = getColumnDisplaySize(column); break; case Types.TINYINT: _precision[column] = 3; break; case Types.SMALLINT: _precision[column] = 5; break; case Types.INTEGER: _precision[column] = 10; break; case Types.BIGINT: _precision[column] = 19; break; case Types.REAL: _precision[column] = 7; break; case Types.DOUBLE: _precision[column] = 15; break; case Types.BOOLEAN: _precision[column] = 5; break; case Types.DATE: _precision[column] = 10; break; case Types.TIME: _precision[column] = 8; break; case Types.TIMESTAMP: _precision[column] = 19; break; default: _precision[column] = 30; break; } } return _precision[column]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Gets the designated column's number of digits to right of * the decimal point. This method is currently very * expensive as it needs to retrieve the information from * the database using an SQL query. * * @param column the first column is 1, the second is 2, ... * @return scale * @throws SQLException if a database access error occurs */ @Override public int getScale(int column) throws SQLException { try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _scale[column]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Indicates the nullability of values in the designated * column. This method is currently very expensive as it * needs to retrieve the information from the database using * an SQL query. * * @param column the first column is 1, the second is 2, ... * @return the nullability status of the given column; one of columnNoNulls, columnNullable or * columnNullableUnknown * @throws SQLException if a database access error occurs */ @Override public int isNullable(int column) throws SQLException { try { if (!_is_fetched[column]) { fetchColumnInfo(column); } return _isNullable[column]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Gets the designated column's table's catalog name. * MonetDB does not support the catalog naming concept as in: catalog.schema.table naming scheme * * @param column the first column is 1, the second is 2, ... * @return the name of the catalog for the table in which the given * column appears or "" if not applicable */ @Override public String getCatalogName(int column) throws SQLException { return null; // MonetDB does NOT support catalogs } /** * Indicates whether the designated column is definitely not writable. MonetDB does not support * cursor updates, so nothing is writable. * * @param column the first column is 1, the second is 2, ... * @return true if so; false otherwise */ @Override public boolean isReadOnly(int column) { return true; } /** * Indicates whether it is possible for a write on the designated column to succeed. * * @param column the first column is 1, the second is 2, ... * @return true if so; false otherwise */ @Override public boolean isWritable(int column) { return false; } /** * Indicates whether a write on the designated column will definitely succeed. * * @param column the first column is 1, the second is 2, ... * @return true if so; false otherwise */ @Override public boolean isDefinitelyWritable(int column) { return false; } /** * Returns the fully-qualified name of the Java class whose * instances are manufactured if the method * ResultSet.getObject is called to retrieve a value from * the column. ResultSet.getObject may return a subclass of * the class returned by this method. * * @param column the first column is 1, the second is 2, ... * @return the fully-qualified name of the class in the Java * programming language that would be used by the method * ResultSet.getObject to retrieve the value in the * specified column. This is the class name used for custom * mapping. * @throws SQLException if there is no such column */ @Override public String getColumnClassName(int column) throws SQLException { if (conn == null) { // first time, get a Connection object and cache it for all next columns conn = getStatement().getConnection(); } try { String MonetDBType = types[column - 1]; Class<?> type = null; if (conn != null) { Map<String,Class<?>> map = conn.getTypeMap(); if (map != null && map.containsKey(MonetDBType)) { type = map.get(MonetDBType); } } if (type == null) { // fallback to the standard SQL type Class mappings type = getClassForType(JdbcSQLTypes[column - 1]); } if (type != null) { return type.getName(); } throw new SQLException("column type mapping null: " + MonetDBType, "M0M03"); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Gets the designated column's suggested title for use in printouts and displays. This is currently equal * to getColumnName(). * * @param column the first column is 1, the second is 2, ... * @return the suggested column title * @throws SQLException if there is no such column */ @Override public String getColumnLabel(int column) throws SQLException { return getColumnName(column); } /** * Gets the designated column's name. * * @param column the first column is 1, the second is 2, ... * @return the column name * @throws SQLException if there is no such column */ @Override public String getColumnName(int column) throws SQLException { try { return columns[column - 1]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * Retrieves the designated column's SQL type. * * @param column the first column is 1, the second is 2, ... * @return SQL type from java.sql.Types * @throws SQLException if there is no such column */ @Override public int getColumnType(int column) throws SQLException { try { return JdbcSQLTypes[column - 1]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } /** * 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. * @throws SQLException if there is no such column */ @Override public String getColumnTypeName(int column) throws SQLException { try { return types[column - 1]; } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(column); } } }; // end of new rsmdw() } // end of getMetaData() /** * Gets the value of the designated column in the current row of this * ResultSet object as an Object in the Java programming language. * * This method will return the value of the given column as a Java object. * The type of the Java object will be the default Java object type * corresponding to the column's SQL type, following the mapping for * 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. In the JDBC 2.0 API, the behavior of method getObject is extended * to materialize data of SQL user-defined types. When a column contains a * structured or distinct value, the behavior of this method is as if it * were a call to: getObject(columnIndex, this.getStatement().getInternalConnection().getTypeMap()). * * @param columnIndex the first column is 1, the second is 2, ... * @return a java.lang.Object holding the column value or null * @throws SQLException if a database access error occurs */ @Override public Object getObject(int columnIndex) throws SQLException { // Many generic JDBC programs use getObject(colnr) to retrieve value objects from a resultset. For speed the // implementation should be as fast as possible, so avoid method calls (by inlining code) where possible final int JdbcType; try { JdbcType = JdbcSQLTypes[columnIndex - 1]; switch(JdbcType) { case Types.BOOLEAN: case Types.TINYINT: case Types.SMALLINT: case Types.INTEGER: case Types.BIGINT: case Types.REAL: case Types.DOUBLE: case Types.DECIMAL: case Types.NUMERIC: case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.LONGVARBINARY: case Types.BLOB: return currentBlock.getValueAsObject(columnIndex - 1); case Types.DATE: return getDate(columnIndex); case Types.TIME: return getTime(columnIndex); case Types.TIMESTAMP: return getTimestamp(columnIndex); case Types.OTHER: { // The MonetDB types: inet, json, url and uuid are all mapped to Types.OTHER in MonetDriver.typeMap // For these MonetDB types (except json, see comments below) we try to create objects of the corresponding class. String MonetDBType = types[columnIndex - 1]; String val = currentBlock.getValueAsString(columnIndex - 1); if (val == null) { return null; } switch (MonetDBType.length()) { case 3: if ("url".equals(MonetDBType)) { try { return new MonetURL(val); } catch (Exception exc) { // ignore exception and just return the val String object return val; } } break; case 4: if ("inet".equals(MonetDBType)) { try { return new MonetINET(val); } catch (Exception exc) { // ignore exception and just return the val String object return val; } } else if ("uuid".equals(MonetDBType)) { try { return UUID.fromString(val); } catch (IllegalArgumentException exc) { // ignore exception and just return the val String object return val; } // } else if ("json".equals(MonetDBType)) { //the same happens for geometry // There is no support for JSON in standard java class libraries. // Possibly we could use org.json.simple.JSONObject or other/faster libs // javax.json.Json is not released yet (see https://json-processing-spec.java.net/) // see also https://github.com/fabienrenaud/java-json-benchmark // Note that it would make our JDBC driver dependent of an external jar // and we don't want that so simply return it as String object } break; } return val; } default: // When we get here the column type is a non-standard JDBC SQL type, possibly a User Defined Type. // Just call getObject(int, Map) for those rare cases. return getObject(columnIndex, this.getStatement().getConnection().getTypeMap()); } } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } catch (ProtocolException e) { throw new SQLException(e); } } private boolean classImplementsSQLData(Class<?> cl) { Class<?>[] cls = cl.getInterfaces(); for (Class<?> cl1 : cls) { if (cl1 == SQLData.class) return true; } return false; } @SuppressWarnings("unchecked") private Object getObjectFromClass(int columnIndex, Class<?> type) throws SQLException { try { if (type == null) { // fallback to the standard Class mappings type = getClassForType(JdbcSQLTypes[columnIndex - 1]); } if (type == null || type == String.class) { return currentBlock.getValueAsString(columnIndex - 1); } else if (type == BigDecimal.class) { return getBigDecimal(columnIndex); } else if (type == Boolean.class) { return getBoolean(columnIndex); } else if (type == Byte.class) { return getByte(columnIndex); } else if (type == Short.class) { return getShort(columnIndex); } else if (type == Integer.class) { return getInt(columnIndex); } else if (type == Long.class) { return getLong(columnIndex); } else if (type == Float.class) { return getFloat(columnIndex); } else if (type == Double.class) { return getDouble(columnIndex); } else if (type == byte[].class) { return getBytes(columnIndex); } else if (type == Date.class) { return getDate(columnIndex); } else if (type == Time.class) { return getTime(columnIndex); } else if (type == Timestamp.class) { return getTimestamp(columnIndex); } else if (type == Clob.class) { return getClob(columnIndex); } else if (type == Blob.class) { return getBlob(columnIndex); } else if (classImplementsSQLData(type)) { SQLData x; try { Constructor<? extends SQLData> ctor = ((Class) type).getConstructor(); x = ctor.newInstance(); } catch (NoSuchMethodException | InstantiationException | InvocationTargetException | SecurityException | IllegalAccessException nsme) { throw new SQLException(nsme.getMessage(), "M0M27"); } final int colnum = columnIndex; final boolean valwasnull = wasNull(); SQLInput input = new SQLInput() { @Override public String readString() throws SQLException { return getString(colnum); } @Override public boolean readBoolean() throws SQLException { return getBoolean(colnum); } @Override public byte readByte() throws SQLException { return getByte(colnum); } @Override public short readShort() throws SQLException { return getShort(colnum); } @Override public int readInt() throws SQLException { return getInt(colnum); } @Override public long readLong() throws SQLException { return getLong(colnum); } @Override public float readFloat() throws SQLException { return getFloat(colnum); } @Override public double readDouble() throws SQLException { return getDouble(colnum); } @Override public BigDecimal readBigDecimal() throws SQLException { return getBigDecimal(colnum); } @Override public byte[] readBytes() throws SQLException { return getBytes(colnum); } @Override public Date readDate() throws SQLException { return getDate(colnum); } @Override public Time readTime() throws SQLException { return getTime(colnum); } @Override public Timestamp readTimestamp() throws SQLException { return getTimestamp(colnum); } @Override public Reader readCharacterStream() throws SQLException { return getCharacterStream(colnum); } @Override public InputStream readAsciiStream() throws SQLException { return getAsciiStream(colnum); } @Override public InputStream readBinaryStream() throws SQLException { return getBinaryStream(colnum); } @Override public Object readObject() throws SQLException { return getObject(colnum); } @Override public Ref readRef() throws SQLException { return getRef(colnum); } @Override public Blob readBlob() throws SQLException { return getBlob(colnum); } @Override public Clob readClob() throws SQLException { return getClob(colnum); } @Override public Array readArray() throws SQLException { return getArray(colnum); } @Override public boolean wasNull() throws SQLException { return valwasnull; } @Override public URL readURL() throws SQLException { return getURL(colnum); } @Override public NClob readNClob() throws SQLException { return getNClob(colnum); } @Override public String readNString() throws SQLException { return getNString(colnum); } @Override public SQLXML readSQLXML() throws SQLException { return getSQLXML(colnum); } @Override public RowId readRowId() throws SQLException { return getRowId(colnum); } }; x.readSQL(input, types[columnIndex - 1]); return x; } else { return currentBlock.getObjectValue(columnIndex - 1); } } catch (ProtocolException e) { throw new SQLException(e); } } /** * Gets the value of the designated column in the current row of this * ResultSet object as an Object in the Java programming language. * * This method will return the value of the given column as a Java object. * The type of the Java object will be the default Java object type corresponding * to the column's SQL type, following the mapping for 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. * In the JDBC 2.0 API, the behavior of method getObject is extended to * materialize data of SQL user-defined types. * * If Connection.getTypeMap does not throw a SQLFeatureNotSupportedException, then * when a column contains a structured or distinct value, the behavior of this * method is as if it were a call to: getObject(columnIndex, * this.getStatement().getInternalConnection().getTypeMap()). * If Connection.getTypeMap does throw a SQLFeatureNotSupportedException, then * structured values are not supported, and distinct values are mapped to the * default Java class as determined by the underlying SQL type of the DISTINCT type. * * @param columnIndex the first column is 1, the second is 2, ... * @param map a java.util.Map object that contains the mapping from SQL * type names to classes in the Java programming language * @return an Object in the Java programming language representing the SQL value * @throws SQLException if a database access error occurs */ @Override public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException { try { String MonetDBtype = types[columnIndex - 1]; Class<?> type = null; if (map != null && map.containsKey(MonetDBtype)) { type = map.get(MonetDBtype); } return getObjectFromClass(columnIndex, type); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row * of this ResultSet object and will convert from the SQL type of * the column to the requested Java data type, if the conversion is * supported. If the conversion is not supported or null is * specified for the type, a SQLException is thrown. * * At a minimum, an implementation must support the conversions defined * in Appendix B, Table B-3 and conversion of appropriate user defined * SQL types to a Java type which implements SQLData, or Struct. * Additional conversions may be supported and are vendor defined. * * @param columnIndex the first column is 1, the second is 2, ... * @param type Class representing the Java data type to convert the designated column to * @return an instance of type holding the column value * @throws SQLException if conversion is not supported, type is null or another error occurs. The getCause() method * of the exception may provide a more detailed exception, for example, if a conversion error occurs */ @Override @SuppressWarnings("unchecked") public <T> T getObject(int columnIndex, Class<T> type) throws SQLException { try { return (T) getObjectFromClass(columnIndex, type); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row * of this ResultSet object and will convert from the SQL type of * the column to the requested Java data type, if the conversion is * supported. If the conversion is not supported or null is * specified for the type, a SQLException is thrown. * * @param columnLabel 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 type Class representing the Java data type to convert the designated column to * @return an instance of type holding the column value * @throws SQLException if conversion is not supported, type is null or another error occurs. The getCause() method * of the exception may provide a more detailed exception, for example, if a conversion error occurs */ @Override public <T> T getObject(String columnLabel, Class<T> type) throws SQLException { return getObject(findColumn(columnLabel), type); } /** * Helper method to support the getObject and ResultsetMetaData.getColumnClassName JDBC methods. * * @param type a value from java.sql.Types * @return a Class object from which an instance would be returned */ static Class<?> getClassForType(int type) { /** * This switch returns the types as objects according to table B-3 from Oracle's JDBC specification 4.1 */ switch(type) { // keep this switch regarding the returned classes aligned with getObject(int, Map) ! case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return String.class; case Types.NUMERIC: case Types.DECIMAL: return BigDecimal.class; case Types.BOOLEAN: return Boolean.class; case Types.TINYINT: return Byte.class; case Types.SMALLINT: return Short.class; case Types.INTEGER: return Integer.class; case Types.BIGINT: return Long.class; case Types.REAL: return Float.class; case Types.DOUBLE: return Double.class; case Types.LONGVARBINARY: return byte[].class; case Types.DATE: return Date.class; case Types.TIME: return Time.class; case Types.TIMESTAMP: return Timestamp.class; case Types.CLOB: return Clob.class; case Types.BLOB: return Blob.class; default: // all the rest are currently not implemented and used return String.class; } } /** * Gets the value of the designated column in the current row of this * ResultSet object as an Object in the Java programming language. * * This method will return the value of the given column as a Java object. * The type of the Java object will be the default Java object type * corresponding to the column's SQL type, following the mapping for * 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. * * @param columnName the SQL name of the column * @return a java.lang.Object holding the column value * @throws SQLException if a database access error occurs */ @Override public Object getObject(String columnName) throws SQLException { return getObject(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row of this * ResultSet object as an Object in the Java programming language. If the * value is an SQL NULL, the driver returns a Java null. This method uses * the specified Map object for custom mapping if appropriate. * * @param colName the name of the column from which to retrieve the value * @param map a java.util.Map object that contains the mapping from SQL * type names to classes in the Java programming language * @return an Object representing the SQL value in the specified column * @throws SQLException if a database access error occurs */ @Override public Object getObject(String colName, Map<String,Class<?>> map) throws SQLException { return getObject(findColumn(colName), map); } @Override public Ref getRef(int i) throws SQLException { throw newSQLFeatureNotSupportedException("getRef"); } @Override public Ref getRef(String colName) throws SQLException { throw newSQLFeatureNotSupportedException("getRef"); } /** * 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 */ @Override public int getRow() { return curRow; } /** * Retrieves the value of the designated column in the current row * of this ResultSet object as a java.sql.RowId 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 * @throws SQLException if there is no such column * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public RowId getRowId(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("getRowId"); } /** * Retrieves the value of the designated column in the current row of this ResultSet object as a java.sql.RowId * 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 * @throws SQLException if the ResultSet object does not contain columnName * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public RowId getRowId(String columnName) throws SQLException { throw newSQLFeatureNotSupportedException("getRowId"); } /** * Retrieves the value of the designated column in the current row of this 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 * @throws SQLException if there is no such column */ @Override public short getShort(int columnIndex) throws SQLException { try { switch (JdbcSQLTypes[columnIndex - 1]) { case Types.SMALLINT: short res = currentBlock.getShortValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : res; case Types.BOOLEAN: boolean bol = currentBlock.getBooleanValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? (short) 0 : (bol ? (short) 1 : (short) 0); case Types.TINYINT: byte bb = currentBlock.getByteValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : bb; case Types.INTEGER: int in = currentBlock.getIntValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (short) in; case Types.BIGINT: long lon = currentBlock.getLongValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (short) lon; case Types.REAL: float floa = currentBlock.getFloatValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (short) Math.round(floa); case Types.DOUBLE: double dou = currentBlock.getDoubleValue(columnIndex - 1); return currentBlock.isLastReadWasNull() ? 0 : (short) Math.round(dou); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? 0 : Short.parseShort(ss); case Types.NUMERIC: case Types.DECIMAL: BigDecimal bigdec = (BigDecimal) currentBlock.getValueAsObject(columnIndex - 1); return bigdec == null ? 0 : bigdec.shortValue(); default: //OTHERS, BLOB, LONGVARBINARY, TIME... throw new SQLException("Conversion from " + types[columnIndex - 1] + " to short type not supported", "M1M05"); } } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this 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 * @throws SQLException if the ResultSet object does not contain columnName */ @Override public short getShort(String columnName) throws SQLException { return getShort(findColumn(columnName)); } /** * Retrieves the Statement object that produced this ResultSet object. If the result set was generated some other * way, such as by a DatabaseMetaData method, this method returns null. * * @return the Statement object that produced this ResultSet object or null if the result set was produced some * other way */ @Override public Statement getStatement() { return statement; } /** * Retrieves the value of the designated column in the current row of this 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 * @throws SQLException if there is no such column */ @Override public String getString(int columnIndex) throws SQLException { try { return currentBlock.getValueAsString(columnIndex - 1); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } } /** * Retrieves the value of the designated column in the current row of this * 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 * @throws SQLException if the ResultSet object does not contain columnName */ @Override public String getString(String columnName) throws SQLException { return getString(findColumn(columnName)); } /** * Retrieves the value of the designated column in the current row * of this ResultSet object as a String in the Java programming * language. It is intended for use when accessing NCHAR,NVARCHAR * 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 * @throws SQLException if there is no such column * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public String getNString(int columnIndex) throws SQLException { return getString(columnIndex); } /** * Retrieves the value of the designated column in the current row * of this ResultSet object as a String in the Java programming * language. It is intended for use when accessing NCHAR,NVARCHAR * 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 * @throws SQLException if the ResultSet object does not contain columnName * @throws SQLFeatureNotSupportedException the JDBC driver does not support this method */ @Override public String getNString(String columnName) throws SQLException { return getNString(findColumn(columnName)); } /** * 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 */ @Override public SQLXML getSQLXML(int i) throws SQLException { throw newSQLFeatureNotSupportedException("getSQLXML"); } /** * 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 * @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 */ @Override public SQLXML getSQLXML(String colName) throws SQLException { throw newSQLFeatureNotSupportedException("getSQLXML"); } /** * 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 * @throws SQLException if a database access error occurs * @see #getDate(int col, Calendar cal) */ @Override public Date getDate(int columnIndex) throws SQLException { return getDate(columnIndex, Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * millisecond value for the date if the underlying database does not 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 date * @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 { try { Calendar res; long millis; switch (JdbcSQLTypes[columnIndex - 1]) { case Types.DATE: case Types.TIME: case Types.TIMESTAMP: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP_WITH_TIMEZONE: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis(); break; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.DATE); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; default: this.addWarning("unsupported data type", "01M03"); cal.clear(); millis = 0; } return new Date(millis); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } 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.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 * @throws SQLException if a database access error occurs */ @Override public Date getDate(String columnName) throws SQLException { return getDate(findColumn(columnName), Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * 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 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 * @throws SQLException if a database access error occurs */ @Override public Date getDate(String columnName, Calendar cal) throws SQLException { return getDate(findColumn(columnName), cal); } /** * 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 * @throws SQLException if a database access error occurs */ @Override public Time getTime(int columnIndex) throws SQLException { return getTime(columnIndex, Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * millisecond value for the time if the underlying database does not 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 * @throws SQLException if a database access error occurs */ @Override public Time getTime(int columnIndex, Calendar cal) throws SQLException { try { Calendar res; long millis; switch (JdbcSQLTypes[columnIndex - 1]) { case Types.DATE: case Types.TIME: case Types.TIMESTAMP: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; case Types.TIME_WITH_TIMEZONE: case Types.TIMESTAMP_WITH_TIMEZONE: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis(); break; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIME); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; default: this.addWarning("unsupported data type", "01M03"); cal.clear(); millis = 0; } return new Time(millis); } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } 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. * * @param columnName the SQL name of the column * @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 Time getTime(String columnName) throws SQLException { return getTime(findColumn(columnName), Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * millisecond value for the time if the underlying database does not store * 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 * @throws SQLException if a database access error occurs */ @Override public Time getTime(String columnName, Calendar cal) throws SQLException { return getTime(findColumn(columnName), cal); } /** * 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 * @throws SQLException if a database access error occurs */ @Override public Timestamp getTimestamp(int columnIndex) throws SQLException { return getTimestamp(columnIndex, Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * millisecond value for the timestamp if the underlying database does not * 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 * @throws SQLException if a database access error occurs */ @Override public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { try { Calendar res; long millis; int nanos = 0; switch (JdbcSQLTypes[columnIndex - 1]) { case Types.DATE: case Types.TIME: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; case Types.TIME_WITH_TIMEZONE: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } millis = res.getTimeInMillis(); break; case Types.TIMESTAMP: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } nanos = currentBlock.getLastNanos(); millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; case Types.TIMESTAMP_WITH_TIMEZONE: res = (Calendar) currentBlock.getValueAsObject(columnIndex - 1); if(res == null) { return null; } nanos = currentBlock.getLastNanos(); millis = res.getTimeInMillis(); break; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: res = currentBlock.getDateValueFromString(this, columnIndex - 1, Types.TIMESTAMP); if(res == null) { return null; } millis = res.getTimeInMillis() - res.getTimeZone().getRawOffset() + cal.getTimeZone().getRawOffset(); break; default: this.addWarning("unsupported data type", "01M03"); cal.clear(); millis = 0; } Timestamp result = new Timestamp(millis); result.setNanos(nanos); return result; } catch (ClassCastException ex) { throw new SQLException(ex.getMessage()); } catch (ProtocolException e) { throw new SQLException(e); } 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. * * @param columnName the SQL name of the column * @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 Timestamp getTimestamp(String columnName) throws SQLException { return getTimestamp(findColumn(columnName), Calendar.getInstance()); } /** * 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. This method uses the given calendar to construct an appropriate * millisecond value for the timestamp if the underlying database does not * store 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 * @throws SQLException if a database access error occurs */ @Override public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { return getTimestamp(findColumn(columnName), cal); } /** * Retrieves the type of this ResultSet object. The type is determined by * the Statement object that created the result set. * * @return ResultSet.TYPE_FORWARD_ONLY, ResultSet.TYPE_SCROLL_INSENSITIVE or ResultSet.TYPE_SCROLL_SENSITIVE */ @Override public int getType() { return type; } /** * 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 */ @Override public URL getURL(int columnIndex) throws SQLException { try { switch(JdbcSQLTypes[columnIndex - 1]) { //if it's a string type, will attempt the conversion case Types.OTHER: if("url".equals(types[columnIndex - 1])) { String ss = currentBlock.getValueAsString(columnIndex - 1); return ss == null ? null : new URL(ss); } break; case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: case Types.BLOB: case Types.LONGVARBINARY: String sss = currentBlock.getValueAsString(columnIndex - 1); return sss == null ? null : new URL(sss); } throw new SQLException("Cannot convert " + types[columnIndex - 1] + " to an url", "M1M05"); } catch (IndexOutOfBoundsException e) { throw newSQLInvalidColumnIndexException(columnIndex); } catch (ProtocolException e) { throw new SQLException(e); } catch (MalformedURLException e) { throw new SQLException(e.getMessage(), "M1M05"); } } /** * 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 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 */ @Override public URL getURL(String columnName) throws SQLException { return getURL(findColumn(columnName)); } /** * Retrieves the first warning reported by calls on this ResultSet object. * If there is more than one warning, subsequent warnings will be chained to * the first one and can be retrieved by calling the method * SQLWarning.getNextWarning on the warning that was retrieved previously. * * This method may not be called on a closed result set; doing so will cause * an SQLException to be thrown. * * Note: Subsequent warnings will be chained to this SQLWarning. * * @return the first SQLWarning object or null if there are none * @throws SQLException if a database access error occurs or this method is * called on a closed connection */ @Override public SQLWarning getWarnings() throws SQLException { if (header != null && header.isClosed()) throw new SQLException("Cannot call on closed ResultSet", "M1M20"); // if there are no warnings, this will be null, which fits with the specification. return warnings; } /** * 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 */ @Override public boolean isAfterLast() { return curRow == tupleCount + 1; } /** * 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 */ @Override public boolean isBeforeFirst() { return curRow == 0; } /** * 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 */ @Override public boolean isClosed() { return header != null && header.isClosed(); } /** * 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 */ @Override public boolean isFirst() { return curRow == 1; } /** * Retrieves whether the cursor is on the last row of this ResultSet object. * * @return true if the cursor is on the last row; false otherwise */ @Override public boolean isLast() { return curRow == tupleCount; } /** * 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 */ @Override public boolean last() throws SQLException { return absolute(-1); } /** * Moves the cursor down one row from its current position. A ResultSet * cursor is initially positioned before the first row; the first call to * the method next makes the first row the current row; the second call * makes the second row the current row, and so on. * * If an input stream is open for the current row, a call to the method * 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 */ @Override public boolean next() throws SQLException { return relative(1); } /** * 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 */ @Override public boolean previous() throws SQLException { return relative(-1); } /** * Moves the cursor a relative number of rows, either positive or negative. * Attempting to move beyond the first/last row in the result set positions * the cursor before/after the the first/last row. Calling relative(0) is * valid, but does not change the cursor position. * * Note: Calling the method relative(1) is identical to calling the method * next() and calling the method relative(-1) is identical to calling the * method previous(). * * @param rows an int specifying the number of rows to move from the current * row; a positive number moves the cursor forward; a negative number * moves the cursor backward * @return true if the cursor is on a row; false otherwise * @throws SQLException if a database access error occurs, there is no current * row, or the result set type is TYPE_FORWARD_ONLY */ @Override public boolean relative(int rows) throws SQLException { return absolute(curRow + rows); } /** * Retrieves whether a row has been deleted. A deleted row may leave a visible "hole" in a result set. * This method can be used to detect holes in a result set. * The value returned depends on whether or not this ResultSet object can detect deletions. * * Note: Support for the rowDeleted method is optional with a result set concurrency of CONCUR_READ_ONLY * * Returns: true if the current row is detected to have been deleted by the owner or another; false otherwise * * Throws: * SQLException - if a database access error occurs or this method is called on a closed result set * SQLFeatureNotSupportedException - if the JDBC driver does not support this method * Since: 1.2 * See Also: DatabaseMetaData.deletesAreDetected(int) */ @Override public boolean rowDeleted() throws SQLException { return false; } /** * Retrieves whether the current row has had an insertion. * The value returned depends on whether or not this ResultSet object can detect visible inserts. * * Note: Support for the rowInserted method is optional with a result set concurrency of CONCUR_READ_ONLY * * Returns: true if the current row is detected to have been inserted; false otherwise * * Throws: * SQLException - if a database access error occurs or this method is called on a closed result set * SQLFeatureNotSupportedException - if the JDBC driver does not support this method * Since: 1.2 * See Also: DatabaseMetaData.insertsAreDetected(int) */ @Override public boolean rowInserted() throws SQLException { return false; } /** * Retrieves whether the current row has been updated. * The value returned depends on whether or not the result set can detect updates. * * Note: Support for the rowUpdated method is optional with a result set concurrency of CONCUR_READ_ONLY * * Returns: true if the current row is detected to have been visibly updated by the owner or another; false otherwise * * Throws: * SQLException - if a database access error occurs or this method is called on a closed result set * SQLFeatureNotSupportedException - if the JDBC driver does not support this method * Since: 1.2 * See Also: DatabaseMetaData.updatesAreDetected(int) */ @Override public boolean rowUpdated() throws SQLException { return false; } /** * Adds a warning to the pile of warnings this ResultSet object has. If * there were no warnings (or clearWarnings was called) this warning will * be the first, otherwise this warning will get appended to the current * warning. * * @param reason the warning message */ public void addWarning(String reason, String sqlstate) { if (warnings == null) { warnings = new SQLWarning(reason, sqlstate); } else { warnings.setNextWarning(new SQLWarning(reason, sqlstate)); } } /* 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"); } @Override public void deleteRow() throws SQLException { throw newSQLFeatureNotSupportedException("deleteRow"); } @Override public void insertRow() throws SQLException { throw newSQLFeatureNotSupportedException("insertRow"); } @Override public void moveToCurrentRow() throws SQLException { throw newSQLFeatureNotSupportedException("moveToCurrentRow"); } @Override public void moveToInsertRow() throws SQLException { throw newSQLFeatureNotSupportedException("moveToInsertRow"); } @Override public void refreshRow() throws SQLException { throw newSQLFeatureNotSupportedException("refreshRow"); } @Override public void updateArray(int columnIndex, Array x) throws SQLException { throw newSQLFeatureNotSupportedException("updateArray"); } @Override public void updateArray(String columnName, Array x) throws SQLException { throw newSQLFeatureNotSupportedException("updateArray"); } @Override public void updateAsciiStream(int columnIndex, InputStream xh) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateAsciiStream(String columnName, InputStream x) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateAsciiStream(String columnName, InputStream x, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateAsciiStream(String columnName, InputStream x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateAsciiStream"); } @Override public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBigDecimal"); } @Override public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBigDecimal"); } @Override public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBinaryStream(String columnName, InputStream x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBinaryStream(String columnName, InputStream x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBinaryStream"); } @Override public void updateBlob(int columnIndex, Blob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBlob(int columnIndex, InputStream s) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBlob(int columnIndex, InputStream s, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBlob(String columnName, Blob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBlob(String columnName, InputStream s) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBlob(String columnName, InputStream s, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateBlob"); } @Override public void updateBoolean(int columnIndex, boolean x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBoolean"); } @Override public void updateBoolean(String columnName, boolean x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBoolean"); } @Override public void updateByte(int columnIndex, byte x) throws SQLException { throw newSQLFeatureNotSupportedException("updateByte"); } @Override public void updateByte(String columnName, byte x) throws SQLException { throw newSQLFeatureNotSupportedException("updateByte"); } @Override public void updateBytes(int columnIndex, byte[] x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBytes"); } @Override public void updateBytes(String columnName, byte[] x) throws SQLException { throw newSQLFeatureNotSupportedException("updateBytes"); } @Override public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateCharacterStream(String columnName, Reader reader) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateCharacterStream(String columnName, Reader reader, int length) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateCharacterStream(String columnName, Reader reader, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateCharacterStream"); } @Override public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } @Override public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } @Override public void updateNCharacterStream(String columnName, Reader reader) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } @Override public void updateNCharacterStream(String columnName, Reader reader, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNCharacterStream"); } @Override public void updateClob(int columnIndex, Clob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateClob(int columnIndex, Reader r) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateClob(int columnIndex, Reader r, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateClob(String columnName, Clob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateClob(String columnName, Reader r) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateClob(String columnName, Reader r, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateClob"); } @Override public void updateNClob(int columnIndex, NClob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateNClob(int columnIndex, Reader r) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateNClob(int columnIndex, Reader r, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateNClob(String columnName, NClob x) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateNClob(String columnName, Reader r) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateNClob(String columnName, Reader r, long length) throws SQLException { throw newSQLFeatureNotSupportedException("updateNClob"); } @Override public void updateDate(int columnIndex, java.sql.Date x) throws SQLException { throw newSQLFeatureNotSupportedException("updateDate"); } @Override public void updateDate(String columnName, java.sql.Date x) throws SQLException { throw newSQLFeatureNotSupportedException("updateDate"); } @Override public void updateDouble(int columnIndex, double x) throws SQLException { throw newSQLFeatureNotSupportedException("updateDouble"); } @Override public void updateDouble(String columnName, double x) throws SQLException { throw newSQLFeatureNotSupportedException("updateDouble"); } @Override public void updateFloat(int columnIndex, float x) throws SQLException { throw newSQLFeatureNotSupportedException("updateFloat"); } @Override public void updateFloat(String columnName, float x) throws SQLException { throw newSQLFeatureNotSupportedException("updateFloat"); } @Override public void updateInt(int columnIndex, int x) throws SQLException { throw newSQLFeatureNotSupportedException("updateInt"); } @Override public void updateInt(String columnName, int x) throws SQLException { throw newSQLFeatureNotSupportedException("updateInt"); } @Override public void updateLong(int columnIndex, long x) throws SQLException { throw newSQLFeatureNotSupportedException("updateLong"); } @Override public void updateLong(String columnName, long x) throws SQLException { throw newSQLFeatureNotSupportedException("updateLong"); } @Override public void updateNull(int columnIndex) throws SQLException { throw newSQLFeatureNotSupportedException("updateNull"); } @Override public void updateNull(String columnName) throws SQLException { throw newSQLFeatureNotSupportedException("updateNull"); } @Override public void updateObject(int columnIndex, Object x) throws SQLException { throw newSQLFeatureNotSupportedException("updateObject"); } @Override public void updateObject(int columnIndex, Object x, int scale) throws SQLException { throw newSQLFeatureNotSupportedException("updateObject"); } @Override public void updateObject(String columnName, Object x) throws SQLException { throw newSQLFeatureNotSupportedException("updateObject"); } @Override public void updateObject(String columnName, Object x, int scale) throws SQLException { throw newSQLFeatureNotSupportedException("updateObject"); } @Override public void updateRef(int columnIndex, Ref x) throws SQLException { throw newSQLFeatureNotSupportedException("updateRef"); } @Override public void updateRef(String columnName, Ref x) throws SQLException { throw newSQLFeatureNotSupportedException("updateRef"); } @Override public void updateRow() throws SQLException { throw newSQLFeatureNotSupportedException("updateRow"); } @Override public void updateRowId(int columnIndex, RowId x) throws SQLException { throw newSQLFeatureNotSupportedException("updateRowId"); } @Override public void updateRowId(String columnLabel, RowId x) throws SQLException { throw newSQLFeatureNotSupportedException("updateRowId"); } @Override public void updateShort(int columnIndex, short x) throws SQLException { throw newSQLFeatureNotSupportedException("updateShort"); } @Override public void updateShort(String columnName, short x) throws SQLException { throw newSQLFeatureNotSupportedException("updateShort"); } @Override public void updateString(int columnIndex, String x) throws SQLException { throw newSQLFeatureNotSupportedException("updateString"); } @Override public void updateString(String columnName, String x) throws SQLException { throw newSQLFeatureNotSupportedException("updateString"); } @Override public void updateNString(int columnIndex, String x) throws SQLException { throw newSQLFeatureNotSupportedException("updateNString"); } @Override public void updateNString(String columnName, String x) throws SQLException { throw newSQLFeatureNotSupportedException("updateNString"); } @Override public void updateSQLXML(String columnName, SQLXML x) throws SQLException { throw newSQLFeatureNotSupportedException("updateSQLXML"); } @Override public void updateSQLXML(int columnIndex, SQLXML x) throws SQLException { throw newSQLFeatureNotSupportedException("updateSQLXML"); } @Override public void updateTime(int columnIndex, Time x) throws SQLException { throw newSQLFeatureNotSupportedException("updateTime"); } @Override public void updateTime(String columnName, Time x) throws SQLException { throw newSQLFeatureNotSupportedException("updateTime"); } @Override public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { throw newSQLFeatureNotSupportedException("updateTimestamp"); } @Override public void updateTimestamp(String columnName, Timestamp x) throws SQLException { throw newSQLFeatureNotSupportedException("updateTimestamp"); } // Chapter 14.2.3.3 Sun JDBC 3.0 Specification /** * Reports whether the last column read had a value of SQL NULL. Note that * you must first call one of the getter methods on a column to try to read * 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 */ @Override public boolean wasNull() { return currentBlock.isLastReadWasNull(); } //== end methods of interface ResultSet /** * Small helper method that formats the "Invalid Column Index number ..." message * and creates a new SQLException object whose SQLState is set to "M1M05". * * @param colIdx the column index number * @return a new created SQLException object with SQLState M1M05 */ static SQLException newSQLInvalidColumnIndexException(int colIdx) { return new SQLException("Invalid Column Index number: " + colIdx, "M1M05"); } /** * Small helper method that formats the "Method ... not implemented" message * and creates a new SQLFeatureNotSupportedException object * whose SQLState is set to "0A000". * * @param name the method name * @return a new created SQLFeatureNotSupportedException object with SQLState 0A000 */ private static SQLFeatureNotSupportedException newSQLFeatureNotSupportedException(String name) { return new SQLFeatureNotSupportedException("Method " + name + " not implemented", "0A000"); } }