// jTDS JDBC Driver for Microsoft SQL Server and Sybase // Copyright (C) 2004 The jTDS Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package net.sourceforge.jtds.jdbc; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Date; import java.sql.NClob; import java.sql.Ref; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.RowId; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Map; /** * jTDS Implementation of the java.sql.ResultSet interface supporting forward read * only result sets. * <p> * Implementation notes: * <ol> * <li>This class is also the base for more sophisticated result sets and * incorporates the update methods required by them. * <li>The class supports the BLOB/CLOB objects added by Brian. * </ol> * * @author Mike Hutchinson * @version $Id: JtdsResultSet.java,v 1.46.2.5 2009-12-30 11:37:21 ickzon Exp $ */ public class JtdsResultSet implements ResultSet { /* * Constants for backwards compatibility with JDK 1.3 */ static final int HOLD_CURSORS_OVER_COMMIT = 1; static final int CLOSE_CURSORS_AT_COMMIT = 2; protected static final int POS_BEFORE_FIRST = 0; protected static final int POS_AFTER_LAST = -1; /** Initial size for row array. */ protected static final int INITIAL_ROW_COUNT = 1000; /* * Protected Instance variables. */ /** The current row number. */ protected int pos = POS_BEFORE_FIRST; /** The number of rows in the result. */ protected int rowsInResult; /** The fetch direction. */ protected int direction = FETCH_FORWARD; /** The result set type. */ protected int resultSetType; /** The result set concurrency. */ protected int concurrency; /** Number of visible columns in row. */ protected int columnCount; /** The array of column descriptors. */ protected ColInfo[] columns; /** The current result set row. */ protected Object[] currentRow; /** Cached row data for forward only result set. */ protected ArrayList rowData; /** Index of current row in rowData. */ protected int rowPtr; /** True if last column retrieved was null. */ protected boolean wasNull; /** The parent statement. */ protected JtdsStatement statement; /** True if this result set is closed. */ protected boolean closed; /** True if the query has been cancelled by another thread. */ protected boolean cancelled; /** The fetch direction. */ protected int fetchDirection = FETCH_FORWARD; /** The fetch size (only applies to cursor <code>ResultSet</code>s). */ protected int fetchSize; /** The cursor name to be used for positioned updates. */ protected String cursorName; /** Cache to optimize findColumn(String) lookups */ private HashMap columnMap; /* * Private instance variables. */ /** Used to format numeric values when scale is specified. */ private static NumberFormat f = NumberFormat.getInstance(); /** * Construct a simple result set from a statement, metadata or generated keys. * * @param statement The parent statement object or null. * @param resultSetType one of FORWARD_ONLY, SCROLL_INSENSITIVE, SCROLL_SENSITIVE. * @param concurrency One of CONCUR_READ_ONLY, CONCUR_UPDATE. * @param columns The array of column descriptors for the result set row. * @throws SQLException */ JtdsResultSet(JtdsStatement statement, int resultSetType, int concurrency, ColInfo[] columns) throws SQLException { if (statement == null) { throw new IllegalArgumentException("Statement parameter must not be null"); } this.statement = statement; this.resultSetType = resultSetType; this.concurrency = concurrency; this.columns = columns; fetchSize = statement.fetchSize; fetchDirection = statement.fetchDirection; cursorName = statement.cursorName; if (columns != null) { columnCount = getColumnCount(columns); rowsInResult = (statement.getTds().isDataInResultSet()) ? 1 : 0; } } /** * Retrieve the column count excluding hidden columns * * @param columns The columns array * @return The new column count as an <code>int</code>. */ protected static int getColumnCount(ColInfo[] columns) { // MJH - Modified to cope with more than one hidden column int i; for (i = columns.length - 1; i >= 0 && columns[i].isHidden; i--); return i + 1; } /** * Retrieve the column descriptor array. * * @return The column descriptors as a <code>ColInfo[]</code>. */ protected ColInfo[] getColumns() { return columns; } /** * Set the specified column's name. * * @param colIndex The index of the column in the row. * @param name The new name. */ protected void setColName(int colIndex, String name) { if (colIndex < 1 || colIndex > columns.length) { throw new IllegalArgumentException("columnIndex " + colIndex + " invalid"); } columns[colIndex - 1].realName = name; } /** * Set the specified column's label. * * @param colIndex The index of the column in the row. * @param name The new label. */ protected void setColLabel(int colIndex, String name) { if (colIndex < 1 || colIndex > columns.length) { throw new IllegalArgumentException("columnIndex " + colIndex + " invalid"); } columns[colIndex - 1].name = name; } /** * Set the specified column's JDBC type. * * @param colIndex The index of the column in the row. * @param jdbcType The new type value. */ protected void setColType(int colIndex, int jdbcType) { if (colIndex < 1 || colIndex > columns.length) { throw new IllegalArgumentException("columnIndex " + colIndex + " invalid"); } columns[colIndex - 1].jdbcType = jdbcType; } /** * Set the specified column's data value. * * @param colIndex index of the column * @param value new column value * @param length the length of a stream parameter * @return the value, possibly converted to an internal type */ protected Object setColValue(int colIndex, int jdbcType, Object value, int length) throws SQLException { checkOpen(); checkUpdateable(); if (colIndex < 1 || colIndex > columnCount) { throw new SQLException(Messages.get("error.resultset.colindex", Integer.toString(colIndex)), "07009"); } // // Convert java date/time objects to internal DateTime objects // if (value instanceof java.sql.Timestamp) { value = new DateTime((java.sql.Timestamp) value); } else if (value instanceof java.sql.Date) { value = new DateTime((java.sql.Date) value); } else if (value instanceof java.sql.Time) { value = new DateTime((java.sql.Time) value); } return value; } /** * Set the current row's column count. * * @param columnCount The number of visible columns in the row. */ protected void setColumnCount(int columnCount) { if (columnCount < 1 || columnCount > columns.length) { throw new IllegalArgumentException("columnCount " + columnCount + " is invalid"); } this.columnCount = columnCount; } /** * Get the specified column's data item. * * @param index the column index in the row * @return the column value as an <code>Object</code> * @throws SQLException if the connection is closed; * if <code>index</code> is less than <code>1</code>; * if <code>index</code> is greater that the number of columns; * if there is no current row */ protected Object getColumn(int index) throws SQLException { checkOpen(); if (index < 1 || index > columnCount) { throw new SQLException(Messages.get("error.resultset.colindex", Integer.toString(index)), "07009"); } if (currentRow == null) { throw new SQLException(Messages.get("error.resultset.norow"), "24000"); } Object data = currentRow[index - 1]; wasNull = data == null; return data; } /** * Check that this connection is still open. * * @throws SQLException if connection closed. */ protected void checkOpen() throws SQLException { if (closed) { throw new SQLException(Messages.get("error.generic.closed", "ResultSet"), "HY010"); } if (cancelled) { throw new SQLException(Messages.get("error.generic.cancelled", "ResultSet"), "HY010"); } } /** * Check that this resultset is scrollable. * * @throws SQLException if connection closed. */ protected void checkScrollable() throws SQLException { if (resultSetType == ResultSet.TYPE_FORWARD_ONLY) { throw new SQLException(Messages.get("error.resultset.fwdonly"), "24000"); } } /** * Check that this resultset is updateable. * * @throws SQLException if connection closed. */ protected void checkUpdateable() throws SQLException { if (concurrency == ResultSet.CONCUR_READ_ONLY) { throw new SQLException(Messages.get("error.resultset.readonly"), "24000"); } } /** * Report that user tried to call a method which has not been implemented. * * @param method The method name to report in the error message. * @throws SQLException */ protected static void notImplemented(String method) throws SQLException { throw new SQLException(Messages.get("error.generic.notimp", method), "HYC00"); } /** * Create a new row containing empty data items. * * @return the new row as an <code>Object</code> array */ protected Object[] newRow() { Object row[] = new Object[columns.length]; return row; } /** * Copy an existing result set row. * * @param row the result set row to copy * @return the new row as an <code>Object</code> array */ protected Object[] copyRow(Object[] row) { Object copy[] = new Object[columns.length]; System.arraycopy(row, 0, copy, 0, row.length); return copy; } /** * Copy an existing result set column descriptor array. * * @param info The result set column descriptors to copy. * @return The new descriptors as a <code>ColInfo[]</code>. */ protected ColInfo[] copyInfo(ColInfo[] info) { ColInfo copy[] = new ColInfo[info.length]; System.arraycopy(info, 0, copy, 0, info.length); return copy; } /** * Retrieve the current row data. * @return The current row data as an <code>Object[]</code>. */ protected Object[] getCurrentRow() { return currentRow; } /** * Cache the remaining results to free up connection. * @throws SQLException */ protected void cacheResultSetRows() throws SQLException { if (rowData == null) { rowData = new ArrayList(INITIAL_ROW_COUNT); } if (currentRow != null) { // Need to create local copy of currentRow // as this is currently a reference to the // row defined in TdsCore currentRow = copyRow(currentRow); } // // Now load the remaining result set rows into memory // while (statement.getTds().getNextRow()) { rowData.add(copyRow(statement.getTds().getRowData())); } // Allow statement to process output vars etc statement.cacheResults(); } /** * Returns the {@link JtdsConnection} object referenced by the * {@link #statement} instance variable. * * @return {@link JtdsConnection} object. * @throws SQLException on error. */ private JtdsConnection getConnection() throws SQLException { return (JtdsConnection) statement.getConnection(); } // // -------------------- java.sql.ResultSet methods ------------------- // public int getConcurrency() throws SQLException { checkOpen(); return concurrency; } public int getFetchDirection() throws SQLException { checkOpen(); return fetchDirection; } public int getFetchSize() throws SQLException { checkOpen(); return fetchSize; } public int getRow() throws SQLException { checkOpen(); return pos > 0 ? pos : 0; } public int getType() throws SQLException { checkOpen(); return resultSetType; } public void afterLast() throws SQLException { checkOpen(); checkScrollable(); } public void beforeFirst() throws SQLException { checkOpen(); checkScrollable(); } public void cancelRowUpdates() throws SQLException { checkOpen(); checkUpdateable(); } public void clearWarnings() throws SQLException { checkOpen(); statement.clearWarnings(); } /** * Retrieves whether this <code>ResultSet</code> object has been closed. A * <code>ResultSet</code> is closed if the method close has been called on * it, or if it is automatically closed. * * @return * true if this <code>ResultSet</code> object is closed; false if it is * still open */ public boolean isClosed() { return closed; } public void close() throws SQLException { if (!closed) { try { if (!getConnection().isClosed()) { // Skip to end of result set // Could send cancel but this is safer as // cancel could kill other statements in a batch. while (next()); } } finally { closed = true; statement = null; } } } public void deleteRow() throws SQLException { checkOpen(); checkUpdateable(); } public void insertRow() throws SQLException { checkOpen(); checkUpdateable(); } public void moveToCurrentRow() throws SQLException { checkOpen(); checkUpdateable(); } public void moveToInsertRow() throws SQLException { checkOpen(); checkUpdateable(); } public void refreshRow() throws SQLException { checkOpen(); checkUpdateable(); } public void updateRow() throws SQLException { checkOpen(); checkUpdateable(); } public boolean first() throws SQLException { checkOpen(); checkScrollable(); return false; } public boolean isAfterLast() throws SQLException { checkOpen(); return (pos == POS_AFTER_LAST) && (rowsInResult != 0); } public boolean isBeforeFirst() throws SQLException { checkOpen(); return (pos == POS_BEFORE_FIRST) && (rowsInResult != 0); } public boolean isFirst() throws SQLException { checkOpen(); return pos == 1; } public boolean isLast() throws SQLException { checkOpen(); if (statement.getTds().isDataInResultSet()) { rowsInResult = pos + 1; // Keep rowsInResult 1 ahead of pos } return (pos == rowsInResult) && (rowsInResult != 0); } public boolean last() throws SQLException { checkOpen(); checkScrollable(); return false; } public boolean next() throws SQLException { checkOpen(); if (pos == POS_AFTER_LAST) { // Make sure nothing will happen after the end has been reached return false; } try { if (rowData != null) { // The rest of the result rows have been cached so // return the next row from the buffer. if (rowPtr < rowData.size()) { currentRow = (Object[])rowData.get(rowPtr); // This is a forward only result set so null out the buffer ref // to allow for garbage collection (we can never access the row // again once we have moved on). rowData.set(rowPtr++, null); pos++; rowsInResult = pos; } else { pos = POS_AFTER_LAST; currentRow = null; } } else { // Need to read from server response if (!statement.getTds().getNextRow()) { statement.cacheResults(); pos = POS_AFTER_LAST; currentRow = null; } else { currentRow = statement.getTds().getRowData(); pos++; rowsInResult = pos; } } // Check for server side errors statement.getMessages().checkErrors(); } catch (NullPointerException npe) { // ResultSet has been closed concurrently throw new SQLException(Messages.get("error.generic.closed", "ResultSet"), "HY010"); } return currentRow != null; } public boolean previous() throws SQLException { checkOpen(); checkScrollable(); return false; } public boolean rowDeleted() throws SQLException { checkOpen(); checkUpdateable(); return false; } public boolean rowInserted() throws SQLException { checkOpen(); checkUpdateable(); return false; } public boolean rowUpdated() throws SQLException { checkOpen(); checkUpdateable(); return false; } public boolean wasNull() throws SQLException { checkOpen(); return wasNull; } public byte getByte(int columnIndex) throws SQLException { return ((Integer) Support.convert(this, getColumn(columnIndex), java.sql.Types.TINYINT, null)).byteValue(); } public short getShort(int columnIndex) throws SQLException { return ((Integer) Support.convert(this, getColumn(columnIndex), java.sql.Types.SMALLINT, null)).shortValue(); } public int getInt(int columnIndex) throws SQLException { return ((Integer) Support.convert(this, getColumn(columnIndex), java.sql.Types.INTEGER, null)).intValue(); } public long getLong(int columnIndex) throws SQLException { return ((Long) Support.convert(this, getColumn(columnIndex), java.sql.Types.BIGINT, null)).longValue(); } public float getFloat(int columnIndex) throws SQLException { return ((Float) Support.convert(this, getColumn(columnIndex), java.sql.Types.REAL, null)).floatValue(); } public double getDouble(int columnIndex) throws SQLException { return ((Double) Support.convert(this, getColumn(columnIndex), java.sql.Types.DOUBLE, null)).doubleValue(); } public void setFetchDirection(int direction) throws SQLException { checkOpen(); switch (direction) { case FETCH_UNKNOWN: case FETCH_REVERSE: if (resultSetType == ResultSet.TYPE_FORWARD_ONLY) { throw new SQLException(Messages.get("error.resultset.fwdonly"), "24000"); } // Fall through case FETCH_FORWARD: fetchDirection = direction; break; default: throw new SQLException( Messages.get("error.generic.badoption", Integer.toString(direction), "direction"), "24000"); } } public void setFetchSize(int rows) throws SQLException { checkOpen(); if (rows < 0 || (statement.getMaxRows() > 0 && rows > statement.getMaxRows())) { throw new SQLException( Messages.get("error.generic.badparam", Integer.toString(rows), "rows"), "HY092"); } if (rows == 0) { rows = statement.getDefaultFetchSize(); } fetchSize = rows; } public void updateNull(int columnIndex) throws SQLException { setColValue(columnIndex, Types.NULL, null, 0); } public boolean absolute(int row) throws SQLException { checkOpen(); checkScrollable(); return false; } public boolean getBoolean(int columnIndex) throws SQLException { return ((Boolean) Support.convert(this, getColumn(columnIndex), JtdsStatement.BOOLEAN, null)).booleanValue(); } public boolean relative(int row) throws SQLException { checkOpen(); checkScrollable(); return false; } public byte[] getBytes(int columnIndex) throws SQLException { checkOpen(); return (byte[]) Support.convert(this, getColumn(columnIndex), java.sql.Types.BINARY, getConnection().getCharset()); } public void updateByte(int columnIndex, byte x) throws SQLException { setColValue(columnIndex, Types.INTEGER, new Integer(x & 0xFF), 0); } public void updateDouble(int columnIndex, double x) throws SQLException { setColValue(columnIndex, Types.DOUBLE, new Double(x), 0); } public void updateFloat(int columnIndex, float x) throws SQLException { setColValue(columnIndex, Types.REAL, new Float(x), 0); } public void updateInt(int columnIndex, int x) throws SQLException { setColValue(columnIndex, Types.INTEGER, new Integer(x), 0); } public void updateLong(int columnIndex, long x) throws SQLException { setColValue(columnIndex, Types.BIGINT, new Long(x), 0); } public void updateShort(int columnIndex, short x) throws SQLException { setColValue(columnIndex, Types.INTEGER, new Integer(x), 0); } public void updateBoolean(int columnIndex, boolean x) throws SQLException { setColValue(columnIndex, Types.BIT, x ? Boolean.TRUE : Boolean.FALSE, 0); } public void updateBytes(int columnIndex, byte[] x) throws SQLException { setColValue(columnIndex, Types.VARBINARY, x, (x != null)? x.length: 0); } public InputStream getAsciiStream(int columnIndex) throws SQLException { Clob clob = getClob(columnIndex); if (clob == null) { return null; } return clob.getAsciiStream(); } public InputStream getBinaryStream(int columnIndex) throws SQLException { Blob blob = getBlob(columnIndex); if (blob == null) { return null; } return blob.getBinaryStream(); } public InputStream getUnicodeStream(int columnIndex) throws SQLException { ClobImpl clob = (ClobImpl) getClob(columnIndex); if (clob == null) { return null; } return clob.getBlobBuffer().getUnicodeStream(); } public void updateAsciiStream(int columnIndex, InputStream inputStream, int length) throws SQLException { if (inputStream == null || length < 0) { updateCharacterStream(columnIndex, null, 0); } else { try { updateCharacterStream(columnIndex, new InputStreamReader(inputStream, "US-ASCII"), length); } catch (UnsupportedEncodingException e) { // Should never happen! } } } public void updateBinaryStream(int columnIndex, InputStream inputStream, int length) throws SQLException { if (inputStream == null || length < 0) { updateBytes(columnIndex, null); return; } setColValue(columnIndex, java.sql.Types.VARBINARY, inputStream, length); } public Reader getCharacterStream(int columnIndex) throws SQLException { Clob clob = getClob(columnIndex); if (clob == null) { return null; } return clob.getCharacterStream(); } public void updateCharacterStream(int columnIndex, Reader reader, int length) throws SQLException { if (reader == null || length < 0) { updateString(columnIndex, null); return; } setColValue(columnIndex, java.sql.Types.VARCHAR, reader, length); } public Object getObject(int columnIndex) throws SQLException { Object value = getColumn(columnIndex); // Don't return UniqueIdentifier objects as the user won't know how to // handle them if (value instanceof UniqueIdentifier) { return value.toString(); } // Don't return DateTime objects as the user won't know how to // handle them if (value instanceof DateTime) { return ((DateTime) value).toObject(); } // If the user requested String/byte[] instead of LOBs, do the conversion if (!getConnection().getUseLOBs()) { value = Support.convertLOB(value); } return value; } public void updateObject(int columnIndex, Object x) throws SQLException { checkOpen(); int length = 0; int jdbcType = Types.VARCHAR; // Use for NULL values if (x != null) { // Need to do some conversion and testing here jdbcType = Support.getJdbcType(x); if (x instanceof BigDecimal) { int prec = getConnection().getMaxPrecision(); x = Support.normalizeBigDecimal((BigDecimal)x, prec); } else if (x instanceof Blob) { Blob blob = (Blob) x; x = blob.getBinaryStream(); length = (int) blob.length(); } else if (x instanceof Clob) { Clob clob = (Clob) x; x = clob.getCharacterStream(); length = (int) clob.length(); } else if (x instanceof String) { length = ((String)x).length(); } else if (x instanceof byte[]) { length = ((byte[])x).length; } if (jdbcType == Types.JAVA_OBJECT) { // Unsupported class of object if (columnIndex < 1 || columnIndex > columnCount) { throw new SQLException(Messages.get("error.resultset.colindex", Integer.toString(columnIndex)), "07009"); } ColInfo ci = columns[columnIndex-1]; throw new SQLException( Messages.get("error.convert.badtypes", x.getClass().getName(), Support.getJdbcTypeName(ci.jdbcType)), "22005"); } } setColValue(columnIndex, jdbcType, x, length); } public void updateObject(int columnIndex, Object x, int scale) throws SQLException { checkOpen(); if (scale < 0 || scale > getConnection().getMaxPrecision()) { throw new SQLException(Messages.get("error.generic.badscale"), "HY092"); } if (x instanceof BigDecimal) { updateObject(columnIndex, ((BigDecimal) x).setScale(scale, BigDecimal.ROUND_HALF_UP)); } else if (x instanceof Number) { synchronized (f) { f.setGroupingUsed(false); f.setMaximumFractionDigits(scale); updateObject(columnIndex, f.format(x)); } } else { updateObject(columnIndex, x); } } public String getCursorName() throws SQLException { checkOpen(); if (cursorName != null) { return cursorName; } throw new SQLException(Messages.get("error.resultset.noposupdate"), "24000"); } public String getString(int columnIndex) throws SQLException { Object tmp = getColumn(columnIndex); if (tmp instanceof String) { return (String) tmp; } return (String) Support.convert(this, tmp, java.sql.Types.VARCHAR, getConnection().getCharset()); } public void updateString(int columnIndex, String x) throws SQLException { setColValue(columnIndex, Types.VARCHAR, x , (x != null)? x.length(): 0); } public byte getByte(String columnName) throws SQLException { return getByte(findColumn(columnName)); } public double getDouble(String columnName) throws SQLException { return getDouble(findColumn(columnName)); } public float getFloat(String columnName) throws SQLException { return getFloat(findColumn(columnName)); } public int findColumn(String columnName) throws SQLException { checkOpen(); if (columnMap == null) { columnMap = new HashMap(columnCount); } else { Object pos = columnMap.get(columnName); if (pos != null) { return ((Integer) pos).intValue(); } } // Rather than use toUpperCase()/toLowerCase(), which are costly, // just do a sequential search. It's actually faster in most cases. for (int i = 0; i < columnCount; i++) { if (columns[i].name.equalsIgnoreCase(columnName)) { columnMap.put(columnName, new Integer(i + 1)); return i + 1; } } throw new SQLException(Messages.get("error.resultset.colname", columnName), "07009"); } public int getInt(String columnName) throws SQLException { return getInt(findColumn(columnName)); } public long getLong(String columnName) throws SQLException { return getLong(findColumn(columnName)); } public short getShort(String columnName) throws SQLException { return getShort(findColumn(columnName)); } public void updateNull(String columnName) throws SQLException { updateNull(findColumn(columnName)); } public boolean getBoolean(String columnName) throws SQLException { return getBoolean(findColumn(columnName)); } public byte[] getBytes(String columnName) throws SQLException { return getBytes(findColumn(columnName)); } public void updateByte(String columnName, byte x) throws SQLException { updateByte(findColumn(columnName), x); } public void updateDouble(String columnName, double x) throws SQLException { updateDouble(findColumn(columnName), x); } public void updateFloat(String columnName, float x) throws SQLException { updateFloat(findColumn(columnName), x); } public void updateInt(String columnName, int x) throws SQLException { updateInt(findColumn(columnName), x); } public void updateLong(String columnName, long x) throws SQLException { updateLong(findColumn(columnName), x); } public void updateShort(String columnName, short x) throws SQLException { updateShort(findColumn(columnName), x); } public void updateBoolean(String columnName, boolean x) throws SQLException { updateBoolean(findColumn(columnName), x); } public void updateBytes(String columnName, byte[] x) throws SQLException { updateBytes(findColumn(columnName), x); } public BigDecimal getBigDecimal(int columnIndex) throws SQLException { return (BigDecimal) Support.convert(this, getColumn(columnIndex), java.sql.Types.DECIMAL, null); } public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { BigDecimal result = (BigDecimal) Support.convert(this, getColumn(columnIndex), java.sql.Types.DECIMAL, null); if (result == null) { return null; } return result.setScale(scale, BigDecimal.ROUND_HALF_UP); } public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { checkOpen(); checkUpdateable(); if (x != null) { int prec = getConnection().getMaxPrecision(); x = Support.normalizeBigDecimal(x, prec); } setColValue(columnIndex, Types.DECIMAL, x, 0); } public URL getURL(int columnIndex) throws SQLException { String url = getString(columnIndex); try { return new java.net.URL(url); } catch (MalformedURLException e) { throw new SQLException(Messages.get("error.resultset.badurl", url), "22000"); } } public Array getArray(int columnIndex) throws SQLException { checkOpen(); notImplemented("ResultSet.getArray()"); return null; } public void updateArray(int columnIndex, Array x) throws SQLException { checkOpen(); checkUpdateable(); notImplemented("ResultSet.updateArray()"); } public Blob getBlob(int columnIndex) throws SQLException { return (Blob) Support.convert(this, getColumn(columnIndex), java.sql.Types.BLOB, null); } public void updateBlob(int columnIndex, Blob x) throws SQLException { if (x == null) { updateBinaryStream(columnIndex, null, 0); } else { updateBinaryStream(columnIndex, x.getBinaryStream(), (int) x.length()); } } public Clob getClob(int columnIndex) throws SQLException { return (Clob) Support.convert(this, getColumn(columnIndex), java.sql.Types.CLOB, null); } public void updateClob(int columnIndex, Clob x) throws SQLException { if (x == null) { updateCharacterStream(columnIndex, null, 0); } else { updateCharacterStream(columnIndex, x.getCharacterStream(), (int) x.length()); } } public Date getDate(int columnIndex) throws SQLException { return (java.sql.Date)Support.convert(this, getColumn(columnIndex), java.sql.Types.DATE, null); } public void updateDate(int columnIndex, Date x) throws SQLException { setColValue(columnIndex, Types.DATE, x, 0); } public Ref getRef(int columnIndex) throws SQLException { checkOpen(); notImplemented("ResultSet.getRef()"); return null; } public void updateRef(int columnIndex, Ref x) throws SQLException { checkOpen(); checkUpdateable(); notImplemented("ResultSet.updateRef()"); } public ResultSetMetaData getMetaData() throws SQLException { checkOpen(); // If this is a DatabaseMetaData built result set, avoid getting an // exception because the statement is closed and assume no LOBs boolean useLOBs = this instanceof CachedResultSet && statement.isClosed() ? false : getConnection().getUseLOBs(); return new JtdsResultSetMetaData(columns, columnCount, useLOBs); } public SQLWarning getWarnings() throws SQLException { checkOpen(); return statement.getWarnings(); } public Statement getStatement() throws SQLException { checkOpen(); return statement; } public Time getTime(int columnIndex) throws SQLException { return (java.sql.Time) Support.convert(this, getColumn(columnIndex), java.sql.Types.TIME, null); } public void updateTime(int columnIndex, Time x) throws SQLException { setColValue(columnIndex, Types.TIME, x, 0); } public Timestamp getTimestamp(int columnIndex) throws SQLException { return (Timestamp) Support.convert(this, getColumn(columnIndex), java.sql.Types.TIMESTAMP, null); } public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { setColValue(columnIndex, Types.TIMESTAMP, x, 0); } public InputStream getAsciiStream(String columnName) throws SQLException { return getAsciiStream(findColumn(columnName)); } public InputStream getBinaryStream(String columnName) throws SQLException { return getBinaryStream(findColumn(columnName)); } public InputStream getUnicodeStream(String columnName) throws SQLException { return getUnicodeStream(findColumn(columnName)); } public void updateAsciiStream(String columnName, InputStream x, int length) throws SQLException { updateAsciiStream(findColumn(columnName), x, length); } public void updateBinaryStream(String columnName, InputStream x, int length) throws SQLException { updateBinaryStream(findColumn(columnName), x, length); } public Reader getCharacterStream(String columnName) throws SQLException { return getCharacterStream(findColumn(columnName)); } public void updateCharacterStream(String columnName, Reader x, int length) throws SQLException { updateCharacterStream(findColumn(columnName), x, length); } public Object getObject(String columnName) throws SQLException { return getObject(findColumn(columnName)); } public void updateObject(String columnName, Object x) throws SQLException { updateObject(findColumn(columnName), x); } public void updateObject(String columnName, Object x, int scale) throws SQLException { updateObject(findColumn(columnName), x, scale); } public Object getObject(int columnIndex, Map map) throws SQLException { notImplemented("ResultSet.getObject(int, Map)"); return null; } public String getString(String columnName) throws SQLException { return getString(findColumn(columnName)); } public void updateString(String columnName, String x) throws SQLException { updateString(findColumn(columnName), x); } public BigDecimal getBigDecimal(String columnName) throws SQLException { return getBigDecimal(findColumn(columnName)); } public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException { return getBigDecimal(findColumn(columnName), scale); } public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException { updateObject(findColumn(columnName), x); } public URL getURL(String columnName) throws SQLException { return getURL(findColumn(columnName)); } public Array getArray(String columnName) throws SQLException { return getArray(findColumn(columnName)); } public void updateArray(String columnName, Array x) throws SQLException { updateArray(findColumn(columnName), x); } public Blob getBlob(String columnName) throws SQLException { return getBlob(findColumn(columnName)); } public void updateBlob(String columnName, Blob x) throws SQLException { updateBlob(findColumn(columnName), x); } public Clob getClob(String columnName) throws SQLException { return getClob(findColumn(columnName)); } public void updateClob(String columnName, Clob x) throws SQLException { updateClob(findColumn(columnName), x); } public Date getDate(String columnName) throws SQLException { return getDate(findColumn(columnName)); } public void updateDate(String columnName, Date x) throws SQLException { updateDate(findColumn(columnName), x); } public Date getDate(int columnIndex, Calendar cal) throws SQLException { java.sql.Date date = getDate(columnIndex); if (date != null && cal != null) { date = new java.sql.Date(Support.timeToZone(date, cal)); } return date; } public Ref getRef(String columnName) throws SQLException { return getRef(findColumn(columnName)); } public void updateRef(String columnName, Ref x) throws SQLException { updateRef(findColumn(columnName), x); } public Time getTime(String columnName) throws SQLException { return getTime(findColumn(columnName)); } public void updateTime(String columnName, Time x) throws SQLException { updateTime(findColumn(columnName), x); } public Time getTime(int columnIndex, Calendar cal) throws SQLException { checkOpen(); java.sql.Time time = getTime(columnIndex); if (time != null && cal != null) { return new Time(Support.timeToZone(time, cal)); } return time; } public Timestamp getTimestamp(String columnName) throws SQLException { return getTimestamp(findColumn(columnName)); } public void updateTimestamp(String columnName, Timestamp x) throws SQLException { updateTimestamp(findColumn(columnName), x); } public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { checkOpen(); Timestamp timestamp = getTimestamp(columnIndex); if (timestamp != null && cal != null) { timestamp = new Timestamp(Support.timeToZone(timestamp, cal)); } return timestamp; } public Object getObject(String columnName, Map map) throws SQLException { return getObject(findColumn(columnName), map); } public Date getDate(String columnName, Calendar cal) throws SQLException { return getDate(findColumn(columnName), cal); } public Time getTime(String columnName, Calendar cal) throws SQLException { return getTime(findColumn(columnName), cal); } public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { return getTimestamp(findColumn(columnName), cal); } /////// JDBC4 demarcation, do NOT put any JDBC3 code below this line /////// /* (non-Javadoc) * @see java.sql.ResultSet#getHoldability() */ public int getHoldability() throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNCharacterStream(int) */ public Reader getNCharacterStream(int columnIndex) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNCharacterStream(java.lang.String) */ public Reader getNCharacterStream(String columnLabel) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNClob(int) */ public NClob getNClob(int columnIndex) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNClob(java.lang.String) */ public NClob getNClob(String columnLabel) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNString(int) */ public String getNString(int columnIndex) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getNString(java.lang.String) */ public String getNString(String columnLabel) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getRowId(int) */ public RowId getRowId(int columnIndex) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getRowId(java.lang.String) */ public RowId getRowId(String columnLabel) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getSQLXML(int) */ public SQLXML getSQLXML(int columnIndex) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#getSQLXML(java.lang.String) */ public SQLXML getSQLXML(String columnLabel) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream) */ public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream) */ public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateAsciiStream(int, java.io.InputStream, long) */ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateAsciiStream(java.lang.String, java.io.InputStream, long) */ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream) */ public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream) */ public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBinaryStream(int, java.io.InputStream, long) */ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBinaryStream(java.lang.String, java.io.InputStream, long) */ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBlob(int, java.io.InputStream) */ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBlob(java.lang.String, java.io.InputStream) */ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBlob(int, java.io.InputStream, long) */ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateBlob(java.lang.String, java.io.InputStream, long) */ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader) */ public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader) */ public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateCharacterStream(int, java.io.Reader, long) */ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateCharacterStream(java.lang.String, java.io.Reader, long) */ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateClob(int, java.io.Reader) */ public void updateClob(int columnIndex, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateClob(java.lang.String, java.io.Reader) */ public void updateClob(String columnLabel, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateClob(int, java.io.Reader, long) */ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateClob(java.lang.String, java.io.Reader, long) */ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNCharacterStream(int, java.io.Reader) */ public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNCharacterStream(java.lang.String, java.io.Reader) */ public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNCharacterStream(int, java.io.Reader, long) */ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNCharacterStream(java.lang.String, java.io.Reader, long) */ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(int, java.sql.NClob) */ public void updateNClob(int columnIndex, NClob clob) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(java.lang.String, java.sql.NClob) */ public void updateNClob(String columnLabel, NClob clob) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(int, java.io.Reader) */ public void updateNClob(int columnIndex, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(java.lang.String, java.io.Reader) */ public void updateNClob(String columnLabel, Reader reader) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(int, java.io.Reader, long) */ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNClob(java.lang.String, java.io.Reader, long) */ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNString(int, java.lang.String) */ public void updateNString(int columnIndex, String string) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateNString(java.lang.String, java.lang.String) */ public void updateNString(String columnLabel, String string) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateRowId(int, java.sql.RowId) */ public void updateRowId(int columnIndex, RowId x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateRowId(java.lang.String, java.sql.RowId) */ public void updateRowId(String columnLabel, RowId x) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateSQLXML(int, java.sql.SQLXML) */ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.ResultSet#updateSQLXML(java.lang.String, java.sql.SQLXML) */ public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Wrapper#isWrapperFor(java.lang.Class) */ public boolean isWrapperFor(Class arg0) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } /* (non-Javadoc) * @see java.sql.Wrapper#unwrap(java.lang.Class) */ public Object unwrap(Class arg0) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } //// JDBC4.1 demarcation, do NOT put any JDBC3/4.0 code below this line //// @Override public <T> T getObject(int columnIndex, Class<T> type) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } @Override public <T> T getObject(String columnLabel, Class<T> type) throws SQLException { // TODO Auto-generated method stub throw new AbstractMethodError(); } }