/* Copyright (C) 2002 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.mysql.jdbc; import com.mysql.jdbc.profiler.ProfileEventSink; import com.mysql.jdbc.profiler.ProfilerEvent; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.StringReader; import java.math.BigDecimal; import java.math.BigInteger; import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; import java.sql.Date; import java.sql.Ref; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; import java.util.TimeZone; /** * A ResultSet provides access to a table of data generated by executing a * Statement. The table rows are retrieved in sequence. Within a row its * column values can be accessed in any order. * *

* A ResultSet 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. *

* *

* The getXXX methods retrieve column values for the current row. You can * retrieve values either using the index number of the column, or by using * the name of the column. In general using the column index will be more * efficient. Columns are numbered from 1. *

* *

* For maximum portability, ResultSet columns within each row should be read in * left-to-right order and each column should be read only once. *

* *

* For the getXXX methods, the JDBC driver attempts to convert the underlying * data to the specified Java type and returns a suitable Java value. See the * JDBC specification for allowable mappings from SQL types to Java types with * the ResultSet getXXX methods. *

* *

* Column names used as input to getXXX methods are case insenstive. When * performing a getXXX using a column name, if several columns have the same * name, then the value of the first matching column will be returned. The * column name option is designed to be used when column names are used in the * SQL Query. For columns that are NOT explicitly named in the query, it is * best to use column numbers. If column names were used there is no way for * the programmer to guarentee that they actually refer to the intended * columns. *

* *

* A ResultSet is automatically closed by the Statement that generated it when * that Statement is closed, re-executed, or is used to retrieve the next * result from a sequence of multiple results. *

* *

* The number, types and properties of a ResultSet's columns are provided by * the ResultSetMetaData object returned by the getMetaData method. *

* * @author Mark Matthews * @version $Id: ResultSet.java,v 1.18.4.45 2004/07/08 19:24:08 mmatthew Exp $ * * @see ResultSetMetaData * @see java.sql.ResultSet */ public class ResultSet implements java.sql.ResultSet { /** Counter used to generate IDs for profiling. */ protected static int resultCounter = 1; /** The Connection instance that created us */ protected com.mysql.jdbc.Connection connection; // The connection that created us /** Map column names (and all of their permutations) to column indices */ protected Map columnNameToIndex = null; /** Map of fully-specified column names to column indices */ protected Map fullColumnNameToIndex = null; protected ProfileEventSink eventSink = null; protected ResultSet nextResultSet = null; /** The actual rows */ protected RowData rowData; // The results /** The warning chain */ protected java.sql.SQLWarning warningChain = null; /** The statement that created us */ protected com.mysql.jdbc.Statement owningStatement; /** The catalog that was in use when we were created */ protected String catalog = null; /** * Any info message from the server that was created while generating this * result set (if 'info parsing' is enabled for the connection). */ protected String serverInfo = null; /** * StackTrace generated where ResultSet was created... used when profiling */ protected Throwable pointOfOrigin; /** Keep track of columns accessed */ protected boolean[] columnUsed = null; /** The fields for this result set */ protected Field[] fields; // The fields /** Pointer to current row data */ protected Object[] thisRow = null; // Values for current row /** Are we in the middle of doing updates to the current row? */ protected boolean doingUpdates = false; protected boolean hasBuiltIndexMapping = false; /** * Is the data stored as strings (default) or natively (which is the case * with results from PrepStmts) */ protected boolean isBinaryEncoded = false; /** Has this result set been closed? */ protected boolean isClosed = false; /** Are we on the insert row? */ protected boolean onInsertRow = false; /** Are we tracking items for profileSql? */ protected boolean profileSql = false; /** * Do we actually contain rows, or just information about * UPDATE/INSERT/DELETE? */ protected boolean reallyResult = false; protected boolean useUsageAdvisor = false; /** Did the previous value retrieval find a NULL? */ protected boolean wasNullFlag = false; /** * First character of the query that created this result set...Used to * determine whether or not to parse server info messages in certain * circumstances. */ protected char firstCharOfQuery; /** The current row #, -1 == before start of result set */ protected int currentRow = -1; // Cursor to current row; /** The direction to fetch rows (always FETCH_FORWARD) */ protected int fetchDirection = FETCH_FORWARD; /** The number of rows to fetch in one go... */ protected int fetchSize = 0; /** The id (used when profiling) to identify us */ protected int resultId; /** Are we read-only or updatable? */ protected int resultSetConcurrency = 0; /** Are we scroll-sensitive/insensitive? */ protected int resultSetType = 0; // These are longs for // recent versions of the MySQL server. // // They get reduced to ints via the JDBC API, // but can be retrieved through a MySQLStatement // in their entirety. // /** How many rows were affected by UPDATE/INSERT/DELETE? */ protected long updateCount; /** Value generated for AUTO_INCREMENT columns */ protected long updateId = -1; private Calendar fastDateCal = null; private TimeZone defaultTimeZone; private boolean useStrictFloatingPoint = false; /** * Create a result set for an executeUpdate statement. * * @param updateCount the number of rows affected by the update * @param updateID the autoincrement value (if any) * @param conn DOCUMENT ME! * @param creatorStmt DOCUMENT ME! */ public ResultSet(long updateCount, long updateID, Connection conn, Statement creatorStmt) { this.updateCount = updateCount; this.updateId = updateID; this.reallyResult = false; this.fields = new Field[0]; this.connection = conn; this.owningStatement = creatorStmt; } /** * Creates a new ResultSet object. * * @param catalog the database in use when we were created * @param fields an array of Field objects (basically, the ResultSet * MetaData) * @param tuples actual row data * @param conn the Connection that created us. * @param creatorStmt DOCUMENT ME! * * @throws SQLException if an error occurs */ public ResultSet(String catalog, Field[] fields, RowData tuples, Connection conn, Statement creatorStmt) throws SQLException { this.connection = conn; if (this.connection != null) { useStrictFloatingPoint = this.connection.getStrictFloatingPoint(); this.setDefaultTimeZone(this.connection.getDefaultTimeZone()); } this.owningStatement = creatorStmt; this.catalog = catalog; this.profileSql = this.connection.getProfileSql(); this.fields = fields; this.rowData = tuples; this.updateCount = (long) rowData.size(); if (Driver.DEBUG) { System.out.println(Messages.getString("ResultSet.Retrieved__1") + updateCount + " rows"); //$NON-NLS-1$ } this.reallyResult = true; // Check for no results if (this.rowData.size() > 0) { if (this.updateCount == 1) { if (this.thisRow == null) { this.rowData.close(); // empty result set this.updateCount = -1; } } } else { this.thisRow = null; } this.rowData.setOwner(this); this.pointOfOrigin = new Throwable(); if (this.profileSql || this.connection.getUseUsageAdvisor()) { this.columnUsed = new boolean[this.fields.length]; this.pointOfOrigin = new Throwable(); this.resultId = resultCounter++; this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); this.eventSink = ProfileEventSink.getInstance(this.connection); } } /** * JDBC 2.0 * *

* Determine if the cursor is after the last row in the result set. *

* * @return true if after the last row, false otherwise. Returns false when * the result set contains no rows. * * @exception SQLException if a database-access error occurs. */ public boolean isAfterLast() throws SQLException { boolean b = rowData.isAfterLast(); return b; } /** * JDBC 2.0 Get an array column. * * @param i the first column is 1, the second is 2, ... * * @return an object representing an SQL array * * @throws SQLException if a database error occurs * @throws NotImplemented DOCUMENT ME! */ public java.sql.Array getArray(int i) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 Get an array column. * * @param colName the column name * * @return an object representing an SQL array * * @throws SQLException if a database error occurs * @throws NotImplemented DOCUMENT ME! */ public java.sql.Array getArray(String colName) throws SQLException { throw new NotImplemented(); } /** * A column value can be retrieved as a stream of ASCII characters and then * read in chunks from the stream. This method is particulary suitable * for retrieving large LONGVARCHAR values. The JDBC driver will do any * necessary conversion from the database format into ASCII. * *

* 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 get method * implicitly closes the stream. Also, a stream may return 0 for * available() whether there is data available or not. *

* * @param columnIndex the first column is 1, the second is 2, ... * * @return a Java InputStream that delivers the database column value as a * stream of one byte ASCII characters. If the value is SQL NULL * then the result is null * * @exception SQLException if a database access error occurs * * @see getBinaryStream */ public InputStream getAsciiStream(int columnIndex) throws SQLException { checkRowPos(); if (!this.isBinaryEncoded) { return getBinaryStream(columnIndex); } else { return getNativeBinaryStream(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public InputStream getAsciiStream(String columnName) throws SQLException { return getAsciiStream(findColumn(columnName)); } //--------------------------------------------------------------------- // Traversal/Positioning //--------------------------------------------------------------------- /** * JDBC 2.0 * *

* Determine if the cursor is before the first row in the result set. *

* * @return true if before the first row, false otherwise. Returns false * when the result set contains no rows. * * @exception SQLException if a database-access error occurs. */ public boolean isBeforeFirst() throws SQLException { return rowData.isBeforeFirst(); } /** * Get the value of a column in the current row as a java.math.BigDecimal * object * * @param columnIndex the first column is 1, the second is 2... * @param scale the number of digits to the right of the decimal * * @return the column value; if the value is SQL NULL, null * * @exception SQLException if a database access error occurs * * @deprecated */ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { if (!this.isBinaryEncoded) { String stringVal = getString(columnIndex); BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val.setScale(scale); } try { val = new BigDecimal(stringVal); } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal", new Object[] { new Integer(columnIndex), stringVal }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } try { return val.setScale(scale); } catch (ArithmeticException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal", new Object[] { new Integer(columnIndex), stringVal }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } return null; } else { return getNativeBigDecimal(columnIndex, scale); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * @param scale DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! * * @deprecated */ public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException { return getBigDecimal(findColumn(columnName), scale); } /** * JDBC 2.0 Get the value of a column in the current row as a * java.math.BigDecimal object. * * @param columnIndex the first column is 1, the second is 2, ... * * @return the column value (full precision); if the value is SQL NULL, the * result is null * * @exception SQLException if a database-access error occurs. */ public BigDecimal getBigDecimal(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { String stringVal = getString(columnIndex); BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val; } try { val = new BigDecimal(stringVal); return val; } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal", new Object[] { new Integer(columnIndex), stringVal }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } return null; } else { return getNativeBigDecimal(columnIndex); } } /** * JDBC 2.0 Get the value of a column in the current row as a * java.math.BigDecimal object. * * @param columnName the name of the column to retrieve the value from * * @return the BigDecimal value in the column * * @throws SQLException if an error occurs */ public BigDecimal getBigDecimal(String columnName) throws SQLException { return getBigDecimal(findColumn(columnName)); } /** * A column value can also be retrieved as a binary strea. This method is * suitable for retrieving LONGVARBINARY values. * * @param columnIndex the first column is 1, the second is 2... * * @return a Java InputStream that delivers the database column value as a * stream of bytes. If the value is SQL NULL, then the result is * null * * @exception SQLException if a database access error occurs * * @see getAsciiStream * @see getUnicodeStream */ public InputStream getBinaryStream(int columnIndex) throws SQLException { checkRowPos(); if (!this.isBinaryEncoded) { byte[] b = getBytes(columnIndex); if (b != null) { return new ByteArrayInputStream(b); } return null; } else { return getNativeBinaryStream(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public InputStream getBinaryStream(String columnName) throws SQLException { return getBinaryStream(findColumn(columnName)); } /** * JDBC 2.0 Get a BLOB column. * * @param columnIndex the first column is 1, the second is 2, ... * * @return an object representing a BLOB * * @throws SQLException if an error occurs. */ public java.sql.Blob getBlob(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); checkColumnBounds(columnIndex); if (checkNull(columnIndex)) { return null; } if (!this.connection.getEmulateLocators()) { return new Blob((byte[]) thisRow[columnIndex - 1]); } else { return new BlobFromLocator(this, columnIndex); } } else { return getNativeBlob(columnIndex); } } /** * JDBC 2.0 Get a BLOB column. * * @param colName the column name * * @return an object representing a BLOB * * @throws SQLException if an error occurs. */ public java.sql.Blob getBlob(String colName) throws SQLException { return getBlob(findColumn(colName)); } /** * Get the value of a column in the current row as a Java boolean * * @param columnIndex the first column is 1, the second is 2... * * @return the column value, false for SQL NULL * * @exception SQLException if a database access error occurs */ public boolean getBoolean(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { String stringVal = getString(columnIndex); if ((stringVal != null) && (stringVal.length() > 0)) { int c = Character.toLowerCase(stringVal.charAt(0)); return ((c == 't') || (c == 'y') || (c == '1') || stringVal.equals("-1")); } return false; } else { return getNativeBoolean(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public boolean getBoolean(String columnName) throws SQLException { return getBoolean(findColumn(columnName)); } /** * Get the value of a column in the current row as a Java byte. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public byte getByte(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); checkColumnBounds(columnIndex); if (checkNull(columnIndex)) { return 0; } Field field = fields[columnIndex - 1]; switch (field.getMysqlType()) { case MysqlDefs.FIELD_TYPE_DECIMAL: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_FLOAT: case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_INT24: try { String stringVal = getString(columnIndex); int decimalIndex = stringVal.indexOf("."); // Strip off the decimals if (decimalIndex != -1) { stringVal = stringVal.substring(0, decimalIndex); } return Byte.parseByte(stringVal); } catch (NumberFormatException NFE) { throw new SQLException(Messages.getString( "ResultSet.Value_is_out_of_range", new Object[] { getString(columnIndex), new Integer(-127), new Integer(127) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } default: try { String stringVal = getString(columnIndex); int decimalIndex = stringVal.indexOf("."); // Strip off the decimals if (decimalIndex != -1) { stringVal = stringVal.substring(0, decimalIndex); } return Byte.parseByte(stringVal); } catch (NumberFormatException NFE) { throw new SQLException(Messages.getString( "ResultSet.Value_is_out_of_range", new Object[] { getString(columnIndex), new Integer(-127), new Integer(127) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } // FIXME: JDBC-Compliance test is broken, wants to convert string->byte(num) //return _thisRow[columnIndex - 1][0]; } } else { return getNativeByte(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public byte getByte(String columnName) throws SQLException { return getByte(findColumn(columnName)); } /** * Get the value of a column in the current row as a Java byte array. * *

* Be warned If the blob is huge, then you may run out of memory. *

* * @param columnIndex the first column is 1, the second is 2, ... * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database access error occurs */ public byte[] getBytes(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); checkColumnBounds(columnIndex); if (checkNull(columnIndex)) { return null; } return (byte[]) thisRow[columnIndex - 1]; } else { return getNativeBytes(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public byte[] getBytes(String columnName) throws SQLException { return getBytes(findColumn(columnName)); } //--------------------------JDBC 2.0----------------------------------- //--------------------------------------------------------------------- // Getter's and Setter's //--------------------------------------------------------------------- /** * JDBC 2.0 * *

* Get the value of a column in the current row as a java.io.Reader. *

* * @param columnIndex the column to get the value from * * @return the value in the column as a java.io.Reader. * * @throws SQLException if an error occurs */ public java.io.Reader getCharacterStream(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { String stringVal = getString(columnIndex); if (stringVal != null) { return new StringReader(stringVal); } else { return null; } } else { return getNativeCharacterStream(columnIndex); } } /** * JDBC 2.0 * *

* Get the value of a column in the current row as a java.io.Reader. *

* * @param columnName the column name to retrieve the value from * * @return the value as a java.io.Reader * * @throws SQLException if an error occurs */ public java.io.Reader getCharacterStream(String columnName) throws SQLException { return getCharacterStream(findColumn(columnName)); } /** * JDBC 2.0 Get a CLOB column. * * @param i the first column is 1, the second is 2, ... * * @return an object representing a CLOB * * @throws SQLException if an error occurs */ public java.sql.Clob getClob(int i) throws SQLException { if (!this.isBinaryEncoded) { return new com.mysql.jdbc.Clob(getString(i)); } else { return getNativeClob(i); } } /** * JDBC 2.0 Get a CLOB column. * * @param colName the column name * * @return an object representing a CLOB * * @throws SQLException if an error occurs */ public java.sql.Clob getClob(String colName) throws SQLException { return getClob(findColumn(colName)); } /** * JDBC 2.0 Return the concurrency of this result set. The concurrency * used is determined by the statement that created the result set. * * @return the concurrency type, CONCUR_READ_ONLY, etc. * * @throws SQLException if a database-access error occurs */ public int getConcurrency() throws SQLException { return (CONCUR_READ_ONLY); } /** * Get the name of the SQL cursor used by this ResultSet * *

* In SQL, a result table is retrieved though a cursor that is named. The * current row of a result can be updated or deleted using a positioned * update/delete statement that references the cursor name. *

* *

* JDBC supports this SQL feature by providing the name of the SQL cursor * used by a ResultSet. The current row of a ResulSet is also the current * row of this SQL cursor. *

* *

* Note: If positioned update is not supported, a SQLException is * thrown. *

* * @return the ResultSet's SQL cursor name. * * @exception SQLException if a database access error occurs */ public String getCursorName() throws SQLException { throw new SQLException(Messages.getString( "ResultSet.Positioned_Update_not_supported"), SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); //$NON-NLS-1$ } /** * Get the value of a column in the current row as a java.sql.Date object * * @param columnIndex the first column is 1, the second is 2... * * @return the column value; null if SQL NULL * * @exception java.sql.SQLException if a database access error occurs */ public java.sql.Date getDate(int columnIndex) throws java.sql.SQLException { return getDate(columnIndex, null); } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws java.sql.SQLException DOCUMENT ME! */ public java.sql.Date getDate(String columnName) throws java.sql.SQLException { return getDate(findColumn(columnName)); } /** * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date * object. Use the calendar to construct an appropriate millisecond value * for the Date, if the underlying database doesn't store timezone * information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the date * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException { if (this.isBinaryEncoded) { return getNativeDate(columnIndex, (cal != null) ? cal.getTimeZone() : this.getDefaultTimeZone()); } else { String stringVal = getString(columnIndex); if (stringVal == null) { return null; } else { return getDateFromString(stringVal, columnIndex); } } } /** * Get the value of a column in the current row as a java.sql.Date object. * Use the calendar to construct an appropriate millisecond value for the * Date, if the underlying database doesn't store timezone information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the date * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException { return getDate(findColumn(columnName), cal); } /** * Get the value of a column in the current row as a Java double. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public double getDouble(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { return getDoubleInternal(columnIndex); } else { return getNativeDouble(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public double getDouble(String columnName) throws SQLException { return getDouble(findColumn(columnName)); } /** * JDBC 2.0 Give a hint as to the direction in which the rows in this * result set will be processed. The initial value is determined by the * statement that produced the result set. The fetch direction may be * changed at any time. * * @param direction the direction to fetch rows in. * * @exception SQLException if a database-access error occurs, or the result * set type is TYPE_FORWARD_ONLY and direction is not * FETCH_FORWARD. MM.MySQL actually ignores this, because it * has the whole result set anyway, so the direction is * immaterial. */ public void setFetchDirection(int direction) throws SQLException { if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE) && (direction != FETCH_UNKNOWN)) { throw new SQLException(Messages.getString( "ResultSet.Illegal_value_for_fetch_direction_64"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } else { fetchDirection = direction; } } /** * JDBC 2.0 Returns the fetch direction for this result set. * * @return the fetch direction for this result set. * * @exception SQLException if a database-access error occurs */ public int getFetchDirection() throws SQLException { return fetchDirection; } /** * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that * should be fetched from the database when more rows are needed for this * result set. If the fetch size specified is zero, then the JDBC driver * ignores the value, and is free to make its own best guess as to what * the fetch size should be. The default value is set by the statement * that creates the result set. The fetch size may be changed at any * time. * * @param rows the number of rows to fetch * * @exception SQLException if a database-access error occurs, or the * condition 0 lteq rows lteq this.getMaxRows() is not * satisfied. Currently ignored by this driver. */ public void setFetchSize(int rows) throws SQLException { if (rows < 0) { /* || rows > getMaxRows()*/ throw new SQLException(Messages.getString( "ResultSet.Value_must_be_between_0_and_getMaxRows()_66"), //$NON-NLS-1$ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } fetchSize = rows; } /** * JDBC 2.0 Return the fetch size for this result set. * * @return the fetch size for this result set. * * @exception SQLException if a database-access error occurs */ public int getFetchSize() throws SQLException { return fetchSize; } /** * JDBC 2.0 * *

* Determine if the cursor is on the first row of the result set. *

* * @return true if on the first row, false otherwise. * * @exception SQLException if a database-access error occurs. */ public boolean isFirst() throws SQLException { return rowData.isFirst(); } /** * Get the value of a column in the current row as a Java float. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public float getFloat(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); String val = null; try { val = getString(columnIndex); if ((val != null) && (val.length() != 0)) { float f = Float.parseFloat(val); return f; } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (float) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getFloat()_-____68") + val //$NON-NLS-1$ + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } else { return getNativeFloat(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public float getFloat(String columnName) throws SQLException { return getFloat(findColumn(columnName)); } /** * Get the value of a column in the current row as a Java int. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public int getInt(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); String val = null; try { val = getString(columnIndex); if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) { return Integer.parseInt(val); } else { // Convert floating point return (int) (Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (int) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getInt()_-____74") + val //$NON-NLS-1$ + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } else { return getNativeInt(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public int getInt(String columnName) throws SQLException { return getInt(findColumn(columnName)); } /** * JDBC 2.0 * *

* Determine if the cursor is on the last row of the result set. Note: * Calling isLast() may be expensive since the JDBC driver might need to * fetch ahead one row in order to determine whether the current row is * the last row in the result set. *

* * @return true if on the last row, false otherwise. * * @exception SQLException if a database-access error occurs. */ public boolean isLast() throws SQLException { return rowData.isLast(); } /** * Get the value of a column in the current row as a Java long. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public long getLong(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); String val = null; try { val = getString(columnIndex); if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) { return Long.parseLong(val); } else { // Convert floating point return Double.doubleToLongBits(Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (long) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getLong()_-____79") + val //$NON-NLS-1$ + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } else { return getNativeLong(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public long getLong(String columnName) throws SQLException { return getLong(findColumn(columnName)); } /** * The numbers, types and properties of a ResultSet's columns are provided * by the getMetaData method * * @return a description of the ResultSet's columns * * @exception SQLException if a database access error occurs */ public java.sql.ResultSetMetaData getMetaData() throws SQLException { return new com.mysql.jdbc.ResultSetMetaData(fields); } /** * Get the value of a column in the current row as a Java object * *

* 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 specified * in the JDBC specification. *

* *

* This method may also be used to read database specific abstract data * types. *

* * @param columnIndex the first column is 1, the second is 2... * * @return a Object holding the column value * * @exception SQLException if a database access error occurs */ public Object getObject(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) return null; // // If they come from a binary-encode result set, // no need to create another new object to represent // the value, just return it directly... // if (this.isBinaryEncoded) { checkColumnBounds(columnIndex); Object columnValue = this.thisRow[columnIndex - 1]; return columnValue; } Field field; field = fields[columnIndex - 1]; switch (field.getSQLType()) { case Types.BIT: return Boolean.valueOf(getBoolean(columnIndex)); case Types.TINYINT: return new Integer(getByte(columnIndex)); case Types.SMALLINT: return new Integer(getInt(columnIndex)); case Types.INTEGER: if (!field.isUnsigned()) { return new Integer(getInt(columnIndex)); } else { return new Long(getLong(columnIndex)); } case Types.BIGINT: if (!field.isUnsigned()) { return new Long(getLong(columnIndex)); } else { String stringVal = getString(columnIndex); if (stringVal == null) { return null; } try { return new BigInteger(stringVal); } catch (NumberFormatException nfe) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigInteger", new Object[] { new Integer(columnIndex), stringVal }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } case Types.DECIMAL: case Types.NUMERIC: String stringVal = getString(columnIndex); BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val; } try { val = new BigDecimal(stringVal); } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$ + stringVal + Messages.getString("ResultSet.___in_column__87") + columnIndex + "(" //$NON-NLS-1$ + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } return val; } else { return null; } case Types.REAL: return new Float(getFloat(columnIndex)); case Types.FLOAT: case Types.DOUBLE: return new Double(getDouble(columnIndex)); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return getString(columnIndex); case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: if (!field.isBlob()) { return getString(columnIndex); } else if (!field.isBinary()) { return getString(columnIndex); } else { byte[] data = getBytes(columnIndex); Object obj = data; if ((data != null) && (data.length >= 2)) { if ((data[0] == -84) && (data[1] == -19)) { // Serialized object? try { ByteArrayInputStream bytesIn = new ByteArrayInputStream(data); ObjectInputStream objIn = new ObjectInputStream(bytesIn); obj = objIn.readObject(); objIn.close(); bytesIn.close(); } catch (ClassNotFoundException cnfe) { throw new SQLException(Messages.getString( "ResultSet.Class_not_found___91") //$NON-NLS-1$ + cnfe.toString() + Messages.getString( "ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$ } catch (IOException ex) { obj = data; // not serialized? } } } return obj; } case Types.DATE: return getDate(columnIndex); case Types.TIME: return getTime(columnIndex); case Types.TIMESTAMP: return getTimestamp(columnIndex); default: return getString(columnIndex); } } /** * Get the value of a column in the current row as a Java object * *

* 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 specified * in the JDBC specification. *

* *

* This method may also be used to read database specific abstract data * types. *

* * @param columnName is the SQL name of the column * * @return a Object holding the column value * * @exception SQLException if a database access error occurs */ public Object getObject(String columnName) throws SQLException { return getObject(findColumn(columnName)); } /** * JDBC 2.0 Returns the value of column i as a Java object. Use the map to * determine the class from which to construct data of SQL structured and * distinct types. * * @param i the first column is 1, the second is 2, ... * @param map the mapping from SQL type names to Java classes * * @return an object representing the SQL value * * @throws SQLException because this is not implemented */ public Object getObject(int i, java.util.Map map) throws SQLException { return getObject(i); } /** * JDBC 2.0 Returns the value of column i as a Java object. Use the map to * determine the class from which to construct data of SQL structured and * distinct types. * * @param colName the column name * @param map the mapping from SQL type names to Java classes * * @return an object representing the SQL value * * @throws SQLException as this is not implemented */ public Object getObject(String colName, java.util.Map map) throws SQLException { return getObject(findColumn(colName), map); } /** * JDBC 2.0 Get a REF(<structured-type>) column. * * @param i the first column is 1, the second is 2, ... * * @return an object representing data of an SQL REF type * * @throws SQLException as this is not implemented * @throws NotImplemented DOCUMENT ME! */ public java.sql.Ref getRef(int i) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 Get a REF(<structured-type>) column. * * @param colName the column name * * @return an object representing data of an SQL REF type * * @throws SQLException as this method is not implemented. * @throws NotImplemented DOCUMENT ME! */ public java.sql.Ref getRef(String colName) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * *

* Determine the current row number. The first row is number 1, the second * number 2, etc. *

* * @return the current row number, else return 0 if there is no current row * * @exception SQLException if a database-access error occurs. */ public int getRow() throws SQLException { int currentRow = rowData.getCurrentRowNumber(); int row = 0; // Non-dynamic result sets can be interrogated // for this information if (!rowData.isDynamic()) { if ((currentRow < 0) || rowData.isAfterLast() || rowData.isEmpty()) { row = 0; } else { row = currentRow + 1; } } else { // dynamic (streaming) can not row = currentRow + 1; } return row; } /** * Get the value of a column in the current row as a Java short. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ public short getShort(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); String val = null; try { val = getString(columnIndex); if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) { return Short.parseShort(val); } else { // Convert floating point return (short) (Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (short) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getShort()_-____96") + val //$NON-NLS-1$ + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } else { return getNativeShort(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ public short getShort(String columnName) throws SQLException { return getShort(findColumn(columnName)); } /** * JDBC 2.0 Return the Statement that produced the ResultSet. * * @return the Statment that produced the result set, or null if the result * was produced some other way. * * @exception SQLException if a database-access error occurs */ public java.sql.Statement getStatement() throws SQLException { return (java.sql.Statement) owningStatement; } /** * Get the value of a column in the current row as a Java String * * @param columnIndex the first column is 1, the second is 2... * * @return the column value, null for SQL NULL * * @exception SQLException if a database access error occurs */ public String getString(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); checkColumnBounds(columnIndex); if (fields == null) { throw new SQLException(Messages.getString( "ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$ SQLError.SQL_STATE_INVALID_COLUMN_NUMBER); } if(checkNull(columnIndex)) { return null; } String stringVal = null; columnIndex--; // JDBC is 1-based, Java is not !? if ((connection != null) && connection.getUseUnicode()) { try { String encoding = this.fields[columnIndex].getCharacterSet(); if (encoding == null) { stringVal = new String((byte[]) thisRow[columnIndex]); } else { SingleByteCharsetConverter converter = this.connection .getCharsetConverter(encoding); if (converter != null) { stringVal = converter.toString((byte[]) thisRow[columnIndex]); } else { stringVal = new String((byte[]) thisRow[columnIndex], encoding); } } } catch (java.io.UnsupportedEncodingException E) { throw new SQLException(Messages.getString( "ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$ + connection.getEncoding() + "'.", "0S100"); } } else { stringVal = StringUtils.toAsciiString((byte[]) thisRow[columnIndex]); } return stringVal; } else { return getNativeString(columnIndex); } } /** * The following routines simply convert the columnName into a columnIndex * and then call the appropriate routine above. * * @param columnName is the SQL name of the column * * @return the column value * * @exception SQLException if a database access error occurs */ public String getString(String columnName) throws SQLException { return getString(findColumn(columnName)); } /** * Get the value of a column in the current row as a java.sql.Time object * * @param columnIndex the first column is 1, the second is 2... * * @return the column value; null if SQL NULL * * @throws java.sql.SQLException if a database access error occurs */ public Time getTime(int columnIndex) throws java.sql.SQLException { return getTimeInternal(columnIndex, this.getDefaultTimeZone()); } /** * Get the value of a column in the current row as a java.sql.Time object. * * @param columnName is the SQL name of the column * * @return the column value; if the value is SQL NULL, the result is null * * @throws java.sql.SQLException if a database-access error occurs. */ public Time getTime(String columnName) throws java.sql.SQLException { return getTime(findColumn(columnName)); } /** * Get the value of a column in the current row as a java.sql.Time object. * Use the calendar to construct an appropriate millisecond value for the * Time, if the underlying database doesn't store timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the time * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException { return getTimeInternal(columnIndex, cal.getTimeZone()); } /** * Get the value of a column in the current row as a java.sql.Time object. * Use the calendar to construct an appropriate millisecond value for the * Time, if the underlying database doesn't store timezone information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the time * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException { return getTime(findColumn(columnName), cal); } /** * Get the value of a column in the current row as a java.sql.Timestamp * object * * @param columnIndex the first column is 1, the second is 2... * * @return the column value; null if SQL NULL * * @exception java.sql.SQLException if a database access error occurs */ public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException { return getTimestampInternal(columnIndex, this.getDefaultTimeZone()); } /** * Get the value of a column in the current row as a java.sql.Timestamp * object. Use the calendar to construct an appropriate millisecond value * for the Timestamp, if the underlying database doesn't store timezone * information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the timestamp * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { return getTimestampInternal(columnIndex, cal.getTimeZone()); } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws java.sql.SQLException DOCUMENT ME! */ public Timestamp getTimestamp(String columnName) throws java.sql.SQLException { return getTimestamp(findColumn(columnName)); } /** * Get the value of a column in the current row as a java.sql.Timestamp * object. Use the calendar to construct an appropriate millisecond value * for the Timestamp, if the underlying database doesn't store timezone * information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the timestamp * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { return getTimestamp(findColumn(columnName), cal); } /** * JDBC 2.0 Return the type of this result set. The type is determined * based on the statement that created the result set. * * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or * TYPE_SCROLL_SENSITIVE * * @exception SQLException if a database-access error occurs */ public int getType() throws SQLException { return resultSetType; } /** * @see ResultSet#getURL(int) */ public URL getURL(int colIndex) throws SQLException { String val = getString(colIndex); if (val == null) { return null; } else { try { return new URL(val); } catch (MalformedURLException mfe) { throw new SQLException(Messages.getString( "ResultSet.Malformed_URL____104") + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } } /** * @see ResultSet#getURL(String) */ public URL getURL(String colName) throws SQLException { String val = getString(colName); if (val == null) { return null; } else { try { return new URL(val); } catch (MalformedURLException mfe) { throw new SQLException(Messages.getString( "ResultSet.Malformed_URL____107") + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } } /** * A column value can also be retrieved as a stream of Unicode characters. * We implement this as a binary stream. * * @param columnIndex the first column is 1, the second is 2... * * @return a Java InputStream that delivers the database column value as a * stream of two byte Unicode characters. If the value is SQL * NULL, then the result is null * * @exception SQLException if a database access error occurs * * @see getAsciiStream * @see getBinaryStream * @deprecated */ public InputStream getUnicodeStream(int columnIndex) throws SQLException { if (!this.isBinaryEncoded) { checkRowPos(); return getBinaryStream(columnIndex); } else { return getNativeBinaryStream(columnIndex); } } /** * DOCUMENT ME! * * @param columnName DOCUMENT ME! * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! * * @deprecated */ public InputStream getUnicodeStream(String columnName) throws SQLException { return getUnicodeStream(findColumn(columnName)); } /** * The first warning reported by calls on this ResultSet is returned. * Subsequent ResultSet warnings will be chained to this * java.sql.SQLWarning. * *

* The warning chain is automatically cleared each time a new row is read. *

* *

* Note: This warning chain only covers warnings caused by ResultSet * methods. Any warnings caused by statement methods (such as reading OUT * parameters) will be chained on the Statement object. *

* * @return the first java.sql.SQLWarning or null; * * @exception SQLException if a database access error occurs. */ public java.sql.SQLWarning getWarnings() throws SQLException { return warningChain; } /** * JDBC 2.0 * *

* Move to an absolute row number in the result set. *

* *

* If row is positive, moves to an absolute row with respect to the * beginning of the result set. The first row is row 1, the second is row * 2, etc. *

* *

* If row is negative, moves to an absolute row position with respect to * the end of result set. For example, calling absolute(-1) positions the * cursor on the last row, absolute(-2) indicates the next-to-last row, * etc. *

* *

* An attempt to position the cursor beyond the first/last row in the * result set, leaves the cursor before/after the first/last row, * respectively. *

* *

* Note: Calling absolute(1) is the same as calling first(). Calling * absolute(-1) is the same as calling last(). *

* * @param row the row number to move to * * @return true if on the result set, false if off. * * @exception SQLException if a database-access error occurs, or row is 0, * or result set type is TYPE_FORWARD_ONLY. */ public boolean absolute(int row) throws SQLException { checkClosed(); boolean b; if (rowData.size() == 0) { b = false; } else { if (row == 0) { throw new SQLException(Messages.getString( "ResultSet.Cannot_absolute_position_to_row_0_110"), //$NON-NLS-1$ SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } if (row == 1) { b = first(); } else if (row == -1) { b = last(); } else if (row > rowData.size()) { afterLast(); b = false; } else { if (row < 0) { // adjust to reflect after end of result set int newRowPosition = rowData.size() + row + 1; if (newRowPosition <= 0) { beforeFirst(); b = false; } else { b = absolute(newRowPosition); } } else { row--; // adjust for index difference rowData.setCurrentRow(row); thisRow = rowData.getAt(row); b = true; } } } return b; } /** * JDBC 2.0 * *

* Moves to the end of the result set, just after the last row. Has no * effect if the result set contains no rows. *

* * @exception SQLException if a database-access error occurs, or result set * type is TYPE_FORWARD_ONLY. */ public void afterLast() throws SQLException { checkClosed(); if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } if (rowData.size() != 0) { rowData.afterLast(); thisRow = null; } } /** * JDBC 2.0 * *

* Moves to the front of the result set, just before the first row. Has no * effect if the result set contains no rows. *

* * @exception SQLException if a database-access error occurs, or result set * type is TYPE_FORWARD_ONLY */ public void beforeFirst() throws SQLException { checkClosed(); if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } if (rowData.size() == 0) { return; } else { rowData.beforeFirst(); thisRow = null; } } /** * JDBC 2.0 The cancelRowUpdates() method may be called after calling an * updateXXX() method(s) and before calling updateRow() to rollback the * updates made to a row. If no updates have been made or updateRow() has * already been called, then this method has no effect. * * @exception SQLException if a database-access error occurs, or if called * when on the insert row. * @throws NotUpdatable DOCUMENT ME! */ public void cancelRowUpdates() throws SQLException { throw new NotUpdatable(); } /** * After this call, getWarnings returns null until a new warning is * reported for this ResultSet * * @exception SQLException if a database access error occurs */ public void clearWarnings() throws SQLException { warningChain = null; } /** * In some cases, it is desirable to immediately release a ResultSet * database and JDBC resources instead of waiting for this to happen when * it is automatically closed. The close method provides this immediate * release. * *

* Note: A ResultSet is automatically closed by the Statement the * Statement that generated it when that Statement is closed, re-executed, * or is used to retrieve the next result from a sequence of multiple * results. A ResultSet is also automatically closed when it is garbage * collected. *

* * @exception SQLException if a database access error occurs */ public void close() throws SQLException { realClose(true); } /** * JDBC 2.0 Delete the current row from the result set and the underlying * database. Cannot be called when on the insert row. * * @exception SQLException if a database-access error occurs, or if called * when on the insert row. * @throws NotUpdatable DOCUMENT ME! */ public void deleteRow() throws SQLException { throw new NotUpdatable(); } /** * Map a ResultSet column name to a ResultSet column index * * @param columnName the name of the column * * @return the column index * * @exception SQLException if a database access error occurs */ public synchronized int findColumn(String columnName) throws SQLException { Integer index; if (!hasBuiltIndexMapping) { buildIndexMapping(); } index = (Integer) columnNameToIndex.get(columnName); if (index == null) { index = (Integer) fullColumnNameToIndex.get(columnName); } if (index != null) { return index.intValue() + 1; } else { // Try this inefficient way, now String columnNameUC = columnName.toUpperCase(); for (int i = 0; i < fields.length; i++) { if (fields[i].getName().toUpperCase().equals(columnNameUC)) { return i + 1; } else if (fields[i].getFullName().toUpperCase().equals(columnNameUC)) { return i + 1; } } throw new SQLException(Messages.getString("ResultSet.Column____112") + columnName + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$ SQLError.SQL_STATE_COLUMN_NOT_FOUND); } } /** * JDBC 2.0 * *

* Moves to the first row in the result set. *

* * @return true if on a valid row, false if no rows in the result set. * * @exception SQLException if a database-access error occurs, or result set * type is TYPE_FORWARD_ONLY. */ public boolean first() throws SQLException { checkClosed(); if (onInsertRow) { onInsertRow = false; } if (rowData.isEmpty()) { return false; } else { if (doingUpdates) { doingUpdates = false; } rowData.beforeFirst(); thisRow = rowData.next(); return true; } } /** * JDBC 2.0 Insert the contents of the insert row into the result set and * the database. Must be on the insert row when this method is called. * * @exception SQLException if a database-access error occurs, if called * when not on the insert row, or if all non-nullable columns * in the insert row have not been given a value * @throws NotUpdatable DOCUMENT ME! */ public void insertRow() throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 * *

* Moves to the last row in the result set. *

* * @return true if on a valid row, false if no rows in the result set. * * @exception SQLException if a database-access error occurs, or result set * type is TYPE_FORWARD_ONLY. */ public boolean last() throws SQLException { checkClosed(); if (rowData.size() == 0) { return false; } else { if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } rowData.beforeLast(); thisRow = rowData.next(); return true; } } /** * JDBC 2.0 Move the cursor to the remembered cursor position, usually the * current row. Has no effect unless the cursor is on the insert row. * * @exception SQLException if a database-access error occurs, or the result * set is not updatable * @throws NotUpdatable DOCUMENT ME! */ public void moveToCurrentRow() throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Move to the insert row. The current cursor position is * remembered while the cursor is positioned on the insert row. The insert * row is a special row associated with an updatable result set. It is * essentially a buffer where a new row may be constructed by calling the * updateXXX() methods prior to inserting the row into the result set. * Only the updateXXX(), getXXX(), and insertRow() methods may be called * when the cursor is on the insert row. All of the columns in a result * set must be given a value each time this method is called before * calling insertRow(). UpdateXXX()must be called before getXXX() on a * column. * * @exception SQLException if a database-access error occurs, or the result * set is not updatable * @throws NotUpdatable DOCUMENT ME! */ public void moveToInsertRow() throws SQLException { throw new NotUpdatable(); } /** * A ResultSet is initially positioned before its first row, the first call * to next makes the first row the current row; the second call makes the * second row the current row, etc. * *

* If an input stream from the previous row is open, it is implicitly * closed. The ResultSet's warning chain is cleared when a new row is * read *

* * @return true if the new current is valid; false if there are no more * rows * * @exception SQLException if a database access error occurs */ public boolean next() throws SQLException { checkClosed(); if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } boolean b; if (!reallyResult()) { throw new SQLException(Messages.getString( "ResultSet.ResultSet_is_from_UPDATE._No_Data_115"), SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ } if (rowData.size() == 0) { b = false; } else { if (!rowData.hasNext()) { // force scroll past end rowData.next(); b = false; } else { clearWarnings(); thisRow = rowData.next(); b = true; } } return b; } /** * The prev method is not part of JDBC, but because of the architecture of * this driver it is possible to move both forward and backward within the * result set. * *

* If an input stream from the previous row is open, it is implicitly * closed. The ResultSet's warning chain is cleared when a new row is * read *

* * @return true if the new current is valid; false if there are no more * rows * * @exception java.sql.SQLException if a database access error occurs */ public boolean prev() throws java.sql.SQLException { checkClosed(); int rowIndex = rowData.getCurrentRowNumber(); if ((rowIndex - 1) >= 0) { rowIndex--; rowData.setCurrentRow(rowIndex); thisRow = rowData.getAt(rowIndex); return true; } else if ((rowIndex - 1) == -1) { rowIndex--; rowData.setCurrentRow(rowIndex); thisRow = null; return false; } else { return false; } } /** * JDBC 2.0 * *

* Moves to the previous row in the result set. *

* *

* Note: previous() is not the same as relative(-1) since it makes sense to * call previous() when there is no current row. *

* * @return true if on a valid row, false if off the result set. * * @exception SQLException if a database-access error occurs, or result set * type is TYPE_FORWAR_DONLY. */ public boolean previous() throws SQLException { if (onInsertRow) { onInsertRow = false; } if (doingUpdates) { doingUpdates = false; } return prev(); } /** * JDBC 2.0 Refresh the value of the current row with its current value in * the database. Cannot be called when on the insert row. The * refreshRow() method provides a way for an application to explicitly * tell the JDBC driver to refetch a row(s) from the database. An * application may want to call refreshRow() when caching or prefetching * is being done by the JDBC driver to fetch the latest value of a row * from the database. The JDBC driver may actually refresh multiple rows * at once if the fetch size is greater than one. All values are refetched * subject to the transaction isolation level and cursor sensitivity. If * refreshRow() is called after calling updateXXX(), but before calling * updateRow() then the updates made to the row are lost. Calling * refreshRow() frequently will likely slow performance. * * @exception SQLException if a database-access error occurs, or if called * when on the insert row. * @throws NotUpdatable DOCUMENT ME! */ public void refreshRow() throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 * *

* Moves 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 relative(1) is different than calling next() since is * makes sense to call next() when there is no current row, for example, * when the cursor is positioned before the first row or after the last * row of the result set. *

* * @param rows the number of relative rows to move the cursor. * * @return true if on a row, false otherwise. * * @throws SQLException if a database-access error occurs, or there is no * current row, or result set type is TYPE_FORWARD_ONLY. */ public boolean relative(int rows) throws SQLException { checkClosed(); if (rowData.size() == 0) { return false; } rowData.moveRowRelative(rows); thisRow = rowData.getAt(rowData.getCurrentRowNumber()); return (!rowData.isAfterLast() && !rowData.isBeforeFirst()); } /** * JDBC 2.0 Determine if this 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 the result set can detect deletions. * * @return true if deleted and deletes are detected * * @exception SQLException if a database-access error occurs * @throws NotImplemented DOCUMENT ME! * * @see DatabaseMetaData#deletesAreDetected */ public boolean rowDeleted() throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 Determine if the current row has been inserted. The value * returned depends on whether or not the result set can detect visible * inserts. * * @return true if inserted and inserts are detected * * @exception SQLException if a database-access error occurs * @throws NotImplemented DOCUMENT ME! * * @see DatabaseMetaData#insertsAreDetected */ public boolean rowInserted() throws SQLException { throw new NotImplemented(); } //--------------------------------------------------------------------- // Updates //--------------------------------------------------------------------- /** * JDBC 2.0 Determine if the current row has been updated. The value * returned depends on whether or not the result set can detect updates. * * @return true if the row has been visibly updated by the owner or * another, and updates are detected * * @exception SQLException if a database-access error occurs * @throws NotImplemented DOCUMENT ME! * * @see DatabaseMetaData#updatesAreDetected */ public boolean rowUpdated() throws SQLException { throw new NotImplemented(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public String toString() { if (this.reallyResult) { return super.toString(); } else { return "Result set representing update count of " + this.updateCount; } } /** * @see ResultSet#updateArray(int, Array) */ public void updateArray(int arg0, Array arg1) throws SQLException { throw new NotImplemented(); } /** * @see ResultSet#updateArray(String, Array) */ public void updateArray(String arg0, Array arg1) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 Update a column with an ascii stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with an ascii stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnName the name of the column * @param x the new column value * @param length of the stream * * @exception SQLException if a database-access error occurs */ public void updateAsciiStream(String columnName, java.io.InputStream x, int length) throws SQLException { updateAsciiStream(findColumn(columnName), x, length); } /** * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException { updateBigDecimal(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a binary stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a binary stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnName the name of the column * @param x the new column value * @param length of the stream * * @exception SQLException if a database-access error occurs */ public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException { updateBinaryStream(findColumn(columnName), x, length); } /** * @see ResultSet#updateBlob(int, Blob) */ public void updateBlob(int arg0, java.sql.Blob arg1) throws SQLException { throw new NotUpdatable(); } /** * @see ResultSet#updateBlob(String, Blob) */ public void updateBlob(String arg0, java.sql.Blob arg1) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateBoolean(int columnIndex, boolean x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateBoolean(String columnName, boolean x) throws SQLException { updateBoolean(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateByte(int columnIndex, byte x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateByte(String columnName, byte x) throws SQLException { updateByte(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a byte array value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateBytes(int columnIndex, byte[] x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a byte array value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateBytes(String columnName, byte[] x) throws SQLException { updateBytes(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a character stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a character stream value. The updateXXX() * methods are used to update column values in the current row, or the * insert row. The updateXXX() methods do not update the underlying * database, instead the updateRow() or insertRow() methods are called to * update the database. * * @param columnName the name of the column * @param reader the stream to update the column with * @param length of the stream * * @throws SQLException if a database-access error occurs */ public void updateCharacterStream(String columnName, java.io.Reader reader, int length) throws SQLException { updateCharacterStream(findColumn(columnName), reader, length); } /** * @see ResultSet#updateClob(int, Clob) */ public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException { throw new NotImplemented(); } /** * @see ResultSet#updateClob(String, Clob) */ public void updateClob(String columnName, java.sql.Clob clob) throws SQLException { updateClob(findColumn(columnName), clob); } /** * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateDate(int columnIndex, java.sql.Date x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateDate(String columnName, java.sql.Date x) throws SQLException { updateDate(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a Double value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateDouble(int columnIndex, double x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a double value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateDouble(String columnName, double x) throws SQLException { updateDouble(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a float value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateFloat(int columnIndex, float x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a float value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateFloat(String columnName, float x) throws SQLException { updateFloat(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with an integer value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateInt(int columnIndex, int x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with an integer value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateInt(String columnName, int x) throws SQLException { updateInt(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a long value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateLong(int columnIndex, long x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a long value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateLong(String columnName, long x) throws SQLException { updateLong(findColumn(columnName), x); } /** * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateNull(int columnIndex) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a null value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * * @exception SQLException if a database-access error occurs */ public void updateNull(String columnName) throws SQLException { updateNull(findColumn(columnName)); } /** * JDBC 2.0 Update a column with an Object value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateObject(int columnIndex, Object x, int scale) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with an Object value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateObject(int columnIndex, Object x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with an Object value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. * * @exception SQLException if a database-access error occurs */ public void updateObject(String columnName, Object x, int scale) throws SQLException { updateObject(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with an Object value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateObject(String columnName, Object x) throws SQLException { updateObject(findColumn(columnName), x); } /** * @see ResultSet#updateRef(int, Ref) */ public void updateRef(int arg0, Ref arg1) throws SQLException { throw new NotImplemented(); } /** * @see ResultSet#updateRef(String, Ref) */ public void updateRef(String arg0, Ref arg1) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 Update the underlying database with the new contents of the * current row. Cannot be called when on the insert row. * * @exception SQLException if a database-access error occurs, or if called * when on the insert row * @throws NotUpdatable DOCUMENT ME! */ public void updateRow() throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a short value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateShort(int columnIndex, short x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a short value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateShort(String columnName, short x) throws SQLException { updateShort(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a String value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateString(int columnIndex, String x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a String value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateString(String columnName, String x) throws SQLException { updateString(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateTime(int columnIndex, java.sql.Time x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are * used to update column values in the current row, or the insert row. The * updateXXX() methods do not update the underlying database, instead the * updateRow() or insertRow() methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateTime(String columnName, java.sql.Time x) throws SQLException { updateTime(findColumn(columnName), x); } /** * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * * @exception SQLException if a database-access error occurs * @throws NotUpdatable DOCUMENT ME! */ public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException { throw new NotUpdatable(); } /** * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods * are used to update column values in the current row, or the insert row. * The updateXXX() methods do not update the underlying database, instead * the updateRow() or insertRow() methods are called to update the * database. * * @param columnName the name of the column * @param x the new column value * * @exception SQLException if a database-access error occurs */ public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException { updateTimestamp(findColumn(columnName), x); } /** * A column may have the value of SQL NULL; wasNull() reports whether the * last column read had this special value. Note that you must first call * getXXX on a column to try to read its value and then call wasNull() to * find if the value was SQL NULL * * @return true if the last column read was SQL NULL * * @exception SQLException if a database access error occurred */ public boolean wasNull() throws SQLException { return wasNullFlag; } /** * Flag that this result set is 'binary' encoded (from a * PreparedStatement), not stored as strings. */ protected void setBinaryEncoded() { this.isBinaryEncoded = true; } /////////////////////////////////////////// // // These number conversion routines save // a ton of "new()s", especially for the heavily // used getInt() and getDouble() methods // /////////////////////////////////////////// /** * Converts a string representation of a number to a double. Need a faster * way to do this. * * @param colIndex the 1-based index of the column to retrieve a double * from. * * @return the double value represented by the string in buf * * @throws SQLException if an error occurs */ protected double getDoubleInternal(int colIndex) throws SQLException { return getDoubleInternal(getString(colIndex), colIndex); } /** * Converts a string representation of a number to a double. Need a faster * way to do this. * * @param stringVal the double as a String * @param colIndex the 1-based index of the column to retrieve a double * from. * * @return the double value represented by the string in buf * * @throws SQLException if an error occurs */ protected double getDoubleInternal(String stringVal, int colIndex) throws SQLException { try { if ((stringVal == null) || (stringVal.length() == 0)) { return 0; } double d = Double.parseDouble(stringVal); if (this.useStrictFloatingPoint) { // Fix endpoint rounding precision loss in MySQL server if (d == 2.147483648E9) { // Fix Odd end-point rounding on MySQL d = 2.147483647E9; } else if (d == 1.0000000036275E-15) { // Fix odd end-point rounding on MySQL d = 1.0E-15; } else if (d == 9.999999869911E14) { d = 9.99999999999999E14; } else if (d == 1.4012984643248E-45) { d = 1.4E-45; } else if (d == 1.4013E-45) { d = 1.4E-45; } else if (d == 3.4028234663853E37) { d = 3.4028235E37; } else if (d == -2.14748E9) { d = -2.147483648E9; } else if (d == 3.40282E37) { d = 3.4028235E37; } } return d; } catch (NumberFormatException e) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_number", new Object[] { stringVal, new Integer(colIndex) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } /** * Sets the first character of the query that this result set was created * from. * * @param c the first character of the query...uppercased */ protected void setFirstCharOfQuery(char c) { this.firstCharOfQuery = c; } /** * Returns the first character of the query that this result set was * created from. * * @return the first character of the query...uppercased */ protected char getFirstCharOfQuery() { return this.firstCharOfQuery; } /** * JDBC 2.0 Get an array column. * * @param i the first column is 1, the second is 2, ... * * @return an object representing an SQL array * * @throws SQLException if a database error occurs * @throws NotImplemented DOCUMENT ME! */ protected java.sql.Array getNativeArray(int i) throws SQLException { throw new NotImplemented(); } /** * A column value can be retrieved as a stream of ASCII characters and then * read in chunks from the stream. This method is particulary suitable * for retrieving large LONGVARCHAR values. The JDBC driver will do any * necessary conversion from the database format into ASCII. * *

* 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 get method * implicitly closes the stream. Also, a stream may return 0 for * available() whether there is data available or not. *

* * @param columnIndex the first column is 1, the second is 2, ... * * @return a Java InputStream that delivers the database column value as a * stream of one byte ASCII characters. If the value is SQL NULL * then the result is null * * @exception SQLException if a database access error occurs * * @see getBinaryStream */ protected InputStream getNativeAsciiStream(int columnIndex) throws SQLException { checkRowPos(); return getNativeBinaryStream(columnIndex); } /** * Get the value of a column in the current row as a java.math.BigDecimal * object * * @param columnIndex the first column is 1, the second is 2... * @param scale the number of digits to the right of the decimal * * @return the column value; if the value is SQL NULL, null * * @exception SQLException if a database access error occurs */ protected BigDecimal getNativeBigDecimal(int columnIndex, int scale) throws SQLException { String stringVal = getNativeString(columnIndex); BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val.setScale(scale); } try { val = new BigDecimal(stringVal); } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal____119") //$NON-NLS-1$ + stringVal + "' in column " + columnIndex + "(" + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } try { return val.setScale(scale); } catch (ArithmeticException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal____124") //$NON-NLS-1$ + stringVal + Messages.getString("ResultSet.___in_column__125") + columnIndex + "(" //$NON-NLS-1$ + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } return null; } /** * JDBC 2.0 Get the value of a column in the current row as a * java.math.BigDecimal object. * * @param columnIndex the first column is 1, the second is 2, ... * * @return the column value (full precision); if the value is SQL NULL, the * result is null * * @exception SQLException if a database-access error occurs. */ protected BigDecimal getNativeBigDecimal(int columnIndex) throws SQLException { String stringVal = getNativeString(columnIndex); return getBigDecimalFromString(stringVal, columnIndex); } /** * A column value can also be retrieved as a binary strea. This method is * suitable for retrieving LONGVARBINARY values. * * @param columnIndex the first column is 1, the second is 2... * * @return a Java InputStream that delivers the database column value as a * stream of bytes. If the value is SQL NULL, then the result is * null * * @exception SQLException if a database access error occurs * * @see getAsciiStream * @see getUnicodeStream */ protected InputStream getNativeBinaryStream(int columnIndex) throws SQLException { checkRowPos(); byte[] b = getNativeBytes(columnIndex); if (b != null) { return new ByteArrayInputStream(b); } else { return null; } } /** * JDBC 2.0 Get a BLOB column. * * @param columnIndex the first column is 1, the second is 2, ... * * @return an object representing a BLOB * * @throws SQLException if an error occurs. */ protected java.sql.Blob getNativeBlob(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } int mysqlType = this.fields[columnIndex - 1].getMysqlType(); byte[] dataAsBytes = null; switch (mysqlType) { case MysqlDefs.FIELD_TYPE_TINY_BLOB: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: case MysqlDefs.FIELD_TYPE_LONG_BLOB: case MysqlDefs.FIELD_TYPE_BLOB: dataAsBytes = (byte[]) thisRow[columnIndex - 1]; default: dataAsBytes = getNativeBytes(columnIndex); } if (!this.connection.getEmulateLocators()) { return new Blob(dataAsBytes); } else { return new BlobFromLocator(this, columnIndex); } } /** * Get the value of a column in the current row as a Java boolean * * @param columnIndex the first column is 1, the second is 2... * * @return the column value, false for SQL NULL * * @exception SQLException if a database access error occurs */ protected boolean getNativeBoolean(int columnIndex) throws SQLException { String stringVal = getNativeString(columnIndex); return getBooleanFromString(stringVal, columnIndex); } /** * Get the value of a column in the current row as a Java byte. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected byte getNativeByte(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } Field field = fields[columnIndex - 1]; switch (field.getMysqlType()) { case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: return (byte) ((Integer) thisRow[columnIndex - 1]).intValue(); case MysqlDefs.FIELD_TYPE_FLOAT: return (byte) ((Float) thisRow[columnIndex - 1]).floatValue(); case MysqlDefs.FIELD_TYPE_DOUBLE: return (byte) ((Double) thisRow[columnIndex - 1]).doubleValue(); case MysqlDefs.FIELD_TYPE_LONGLONG: return (byte) ((Long) thisRow[columnIndex - 1]).longValue(); default: return getByteFromString(getNativeString(columnIndex), columnIndex); } } /** * Get the value of a column in the current row as a Java byte array. * *

* Be warned If the blob is huge, then you may run out of memory. *

* * @param columnIndex the first column is 1, the second is 2, ... * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database access error occurs */ protected byte[] getNativeBytes(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } int mysqlType = this.fields[columnIndex - 1].getMysqlType(); switch (mysqlType) { case MysqlDefs.FIELD_TYPE_TINY_BLOB: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: case MysqlDefs.FIELD_TYPE_LONG_BLOB: case MysqlDefs.FIELD_TYPE_BLOB: return (byte[]) thisRow[columnIndex - 1]; default: return getBytesFromString(getNativeString(columnIndex), columnIndex); } } protected Object getObjectStoredProc(String columnName, int desiredSqlType) throws SQLException { return getObjectStoredProc(findColumn(columnName), desiredSqlType); } protected Object getObjectStoredProc(String colName, java.util.Map map, int desiredSqlType) throws SQLException { return getObjectStoredProc(findColumn(colName), map, desiredSqlType); } protected Object getObjectStoredProc(int i, java.util.Map map, int desiredSqlType) throws SQLException { return getObjectStoredProc(i, desiredSqlType); } protected Object getObjectStoredProc(int columnIndex, int desiredSqlType) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } Field field; field = fields[columnIndex - 1]; switch (desiredSqlType) { case Types.BIT: return Boolean.valueOf(getBoolean(columnIndex)); case Types.TINYINT: return new Integer(getInt(columnIndex)); case Types.SMALLINT: return new Integer(getInt(columnIndex)); case Types.INTEGER: if (field.isUnsigned()) { return new Long(getLong(columnIndex)); } else { return new Integer(getInt(columnIndex)); } case Types.BIGINT: if (field.isUnsigned()) { return getBigDecimal(columnIndex); } else { return new Long(getLong(columnIndex)); } case Types.DECIMAL: case Types.NUMERIC: String stringVal = getString(columnIndex); BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val; } try { val = new BigDecimal(stringVal); } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$ + stringVal + Messages.getString("ResultSet.___in_column__87") + columnIndex + "(" //$NON-NLS-1$ + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } return val; } else { return null; } case Types.REAL: return new Float(getFloat(columnIndex)); case Types.FLOAT: case Types.DOUBLE: return new Double(getDouble(columnIndex)); case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: return getString(columnIndex); case Types.BINARY: case Types.VARBINARY: case Types.LONGVARBINARY: if (!field.isBlob()) { return getString(columnIndex); } else if (!field.isBinary()) { return getString(columnIndex); } else { byte[] data = getBytes(columnIndex); Object obj = data; if ((data != null) && (data.length >= 2)) { if ((data[0] == -84) && (data[1] == -19)) { // Serialized object? try { ByteArrayInputStream bytesIn = new ByteArrayInputStream(data); ObjectInputStream objIn = new ObjectInputStream(bytesIn); obj = objIn.readObject(); objIn.close(); bytesIn.close(); } catch (ClassNotFoundException cnfe) { throw new SQLException(Messages.getString( "ResultSet.Class_not_found___91") //$NON-NLS-1$ + cnfe.toString() + Messages.getString( "ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$ } catch (IOException ex) { obj = data; // not serialized? } } } return obj; } case Types.DATE: return getDate(columnIndex); case Types.TIME: return getTime(columnIndex); case Types.TIMESTAMP: return getTimestamp(columnIndex); default: return getString(columnIndex); } } /** * Checks if columnIndex is within the number of columns in this result * set. * * @param columnIndex the index to check * * @throws SQLException if the index is out of bounds */ protected final void checkColumnBounds(int columnIndex) throws SQLException { if ((columnIndex < 1) || (columnIndex > fields.length)) { throw new SQLException(Messages.getString( "ResultSet.Column_Index_out_of_range", new Object[] { new Integer(columnIndex), new Integer(this.fields.length) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } if (this.profileSql || this.useUsageAdvisor) { this.columnUsed[columnIndex - 1] = true; } } /** * Check if the specified column has a null value, and set the wasNullFlag appropriatly. */ private boolean checkNull(int columnIndex) throws SQLException { if(thisRow == null) { wasNullFlag = true; } else if (thisRow[columnIndex - 1] == null) { wasNullFlag = true; } else { wasNullFlag = false; } return wasNullFlag; } //--------------------------JDBC 2.0----------------------------------- //--------------------------------------------------------------------- // Getter's and Setter's //--------------------------------------------------------------------- /** * JDBC 2.0 * *

* Get the value of a column in the current row as a java.io.Reader. *

* * @param columnIndex the column to get the value from * * @return the value in the column as a java.io.Reader. * * @throws SQLException if an error occurs */ protected java.io.Reader getNativeCharacterStream(int columnIndex) throws SQLException { String stringVal = getNativeString(columnIndex); return getCharacterStreamFromString(stringVal, columnIndex); } /** * JDBC 2.0 Get a CLOB column. * * @param columnIndex the first column is 1, the second is 2, ... * * @return an object representing a CLOB * * @throws SQLException if an error occurs */ protected java.sql.Clob getNativeClob(int columnIndex) throws SQLException { String stringVal = getNativeString(columnIndex); return getClobFromString(stringVal, columnIndex); } /** * Get the value of a column in the current row as a java.sql.Date object * * @param columnIndex the first column is 1, the second is 2... * * @return the column value; null if SQL NULL * * @exception SQLException if a database access error occurs */ protected java.sql.Date getNativeDate(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) { return (java.sql.Date) thisRow[columnIndex - 1]; } else { String stringVal = getNativeString(columnIndex); return getDateFromString(stringVal, columnIndex); } } /** * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date * object. Use the calendar to construct an appropriate millisecond value * for the Date, if the underlying database doesn't store timezone * information. * * @param columnIndex the first column is 1, the second is 2, ... * @param tz the calendar to use in constructing the date * * @return the column value; if the value is SQL NULL, the result is null * * @exception SQLException if a database-access error occurs. */ protected java.sql.Date getNativeDate(int columnIndex, TimeZone tz) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } int mysqlType = this.fields[columnIndex - 1].getMysqlType(); if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) { return (java.sql.Date) this.thisRow[columnIndex - 1]; } else { String strDate = getNativeString(columnIndex); return getDateFromString(strDate, columnIndex); } } /** * Get the value of a column in the current row as a Java double. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected double getNativeDouble(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } switch (this.fields[columnIndex-1].getMysqlType()) { case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_FLOAT: return ((Number) thisRow[columnIndex-1]).doubleValue(); default: String stringVal = getNativeString(columnIndex); return getDoubleFromString(stringVal, columnIndex); } } /** * Get the value of a column in the current row as a Java float. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected float getNativeFloat(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } switch (this.fields[columnIndex-1].getMysqlType()) { case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_FLOAT: return ((Number) thisRow[columnIndex-1]).floatValue(); default: String stringVal = getNativeString(columnIndex); return getFloatFromString(stringVal, columnIndex); } } /** * Get the value of a column in the current row as a Java int. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected int getNativeInt(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } switch (this.fields[columnIndex-1].getMysqlType()) { case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_FLOAT: return ((Number) thisRow[columnIndex-1]).intValue(); default: String stringVal = getNativeString(columnIndex); return getIntFromString(stringVal, columnIndex); } } /** * Get the value of a column in the current row as a Java long. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected long getNativeLong(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } switch (this.fields[columnIndex-1].getMysqlType()) { case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_FLOAT: return ((Number) thisRow[columnIndex-1]).longValue(); default: String stringVal = getNativeString(columnIndex); return getLongFromString(stringVal, columnIndex); } } /** * JDBC 2.0 Get a REF(<structured-type>) column. * * @param i the first column is 1, the second is 2, ... * * @return an object representing data of an SQL REF type * * @throws SQLException as this is not implemented * @throws NotImplemented DOCUMENT ME! */ protected java.sql.Ref getNativeRef(int i) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a Java short. * * @param columnIndex the first column is 1, the second is 2,... * * @return the column value; 0 if SQL NULL * * @exception SQLException if a database access error occurs */ protected short getNativeShort(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return 0; } switch (this.fields[columnIndex-1].getMysqlType()) { case MysqlDefs.FIELD_TYPE_DOUBLE: case MysqlDefs.FIELD_TYPE_TINY: case MysqlDefs.FIELD_TYPE_SHORT: case MysqlDefs.FIELD_TYPE_LONG: case MysqlDefs.FIELD_TYPE_LONGLONG: case MysqlDefs.FIELD_TYPE_FLOAT: return ((Number) thisRow[columnIndex-1]).shortValue(); default: String stringVal = getNativeString(columnIndex); return getShortFromString(stringVal, columnIndex); } } /** * Get the value of a column in the current row as a Java String * * @param columnIndex the first column is 1, the second is 2... * * @return the column value, null for SQL NULL * * @exception SQLException if a database access error occurs */ protected String getNativeString(int columnIndex) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if (fields == null) { throw new SQLException(Messages.getString( "ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$ SQLError.SQL_STATE_INVALID_COLUMN_NUMBER); } if(checkNull(columnIndex)) { return null; } String stringVal = null; if (this.thisRow[columnIndex - 1] instanceof String) { return (String) this.thisRow[columnIndex - 1]; } Field field = this.fields[columnIndex - 1]; int mysqlType = field.getMysqlType(); switch (mysqlType) { case MysqlDefs.FIELD_TYPE_TINY_BLOB: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB: case MysqlDefs.FIELD_TYPE_LONG_BLOB: case MysqlDefs.FIELD_TYPE_BLOB: if ((this.connection != null) && this.connection.getUseUnicode()) { try { String encoding = this.fields[columnIndex - 1] .getCharacterSet(); if (encoding == null) { stringVal = new String((byte[]) thisRow[columnIndex - 1]); } else { SingleByteCharsetConverter converter = this.connection .getCharsetConverter(encoding); if (converter != null) { stringVal = converter.toString((byte[]) thisRow[columnIndex - 1]); } else { stringVal = new String((byte[]) thisRow[columnIndex - 1], encoding); } } } catch (java.io.UnsupportedEncodingException E) { throw new SQLException(Messages.getString( "ResultSet.Unsupported_character_encoding____135") //$NON-NLS-1$ + connection.getEncoding() + "'.", "0S100"); } } else { stringVal = StringUtils.toAsciiString((byte[]) thisRow[columnIndex - 1]); } // Cache this conversion if the type is a MySQL string type if ((mysqlType == MysqlDefs.FIELD_TYPE_STRING) || (mysqlType == MysqlDefs.FIELD_TYPE_VAR_STRING)) { this.thisRow[columnIndex - 1] = stringVal; } return stringVal; case MysqlDefs.FIELD_TYPE_VAR_STRING: case MysqlDefs.FIELD_TYPE_STRING: try { return (String) this.thisRow[columnIndex - 1]; } catch (ClassCastException cce) { ; // ignore, we're not really a String yet } if ((this.connection != null) && this.connection.getUseUnicode()) { try { String encoding = this.fields[columnIndex - 1] .getCharacterSet(); if (encoding == null) { stringVal = new String((byte[]) thisRow[columnIndex - 1]); } else { SingleByteCharsetConverter converter = this.connection .getCharsetConverter(encoding); if (converter != null) { stringVal = converter.toString((byte[]) thisRow[columnIndex - 1]); } else { stringVal = new String((byte[]) thisRow[columnIndex - 1], encoding); } } } catch (java.io.UnsupportedEncodingException E) { throw new SQLException(Messages.getString( "ResultSet.Unsupported_character_encoding____138") //$NON-NLS-1$ + connection.getEncoding() + "'.", "0S100"); } } else { stringVal = StringUtils.toAsciiString((byte[]) thisRow[columnIndex - 1]); } // Cache this conversion if the type is a MySQL string type if ((mysqlType == MysqlDefs.FIELD_TYPE_STRING) || (mysqlType == MysqlDefs.FIELD_TYPE_VAR_STRING)) { this.thisRow[columnIndex - 1] = stringVal; } return stringVal; default: stringVal = this.thisRow[columnIndex - 1].toString(); if (field.isZeroFill() && (stringVal != null)) { int origLength = stringVal.length(); StringBuffer zeroFillBuf = new StringBuffer(origLength); int numZeros = field.getLength() - origLength; for (int i = 0; i < numZeros; i++) { zeroFillBuf.append('0'); } zeroFillBuf.append(stringVal); stringVal = zeroFillBuf.toString(); } return stringVal; } } /** * @see ResultSet#getURL(int) */ protected URL getNativeURL(int colIndex) throws SQLException { String val = getString(colIndex); if (val == null) { return null; } else { try { return new URL(val); } catch (MalformedURLException mfe) { throw new SQLException(Messages.getString( "ResultSet.Malformed_URL____141") + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } } /** * Converts the given value as a java long, to an 'unsigned' long, * using the java.math.BigInteger class. */ protected static BigInteger convertLongToUlong(long longVal) { byte[] asBytes = new byte[8]; asBytes[0] = (byte) (longVal & 0xff); asBytes[1] = (byte) (longVal >>> 8); asBytes[2] = (byte) (longVal >>> 16); asBytes[3] = (byte) (longVal >>> 24); asBytes[4] = (byte) (longVal >>> 32); asBytes[5] = (byte) (longVal >>> 40); asBytes[6] = (byte) (longVal >>> 48); asBytes[7] = (byte) (longVal >>> 56); return new BigInteger(1, asBytes); } /** * A column value can also be retrieved as a stream of Unicode characters. * We implement this as a binary stream. * * @param columnIndex the first column is 1, the second is 2... * * @return a Java InputStream that delivers the database column value as a * stream of two byte Unicode characters. If the value is SQL * NULL, then the result is null * * @exception SQLException if a database access error occurs * * @see getAsciiStream * @see getBinaryStream */ protected InputStream getNativeUnicodeStream(int columnIndex) throws SQLException { checkRowPos(); return getBinaryStream(columnIndex); } /** * DOCUMENT ME! * * @param nextResultSet Sets the next result set in the result set chain * for multiple result sets. */ protected void setNextResultSet(ResultSet nextResultSet) { this.nextResultSet = nextResultSet; } /** * DOCUMENT ME! * * @return Returns the nextResultSet, if any, null if none exists. */ protected ResultSet getNextResultSet() { return nextResultSet; } /** * Sets the concurrency (JDBC2) * * @param concurrencyFlag CONCUR_UPDATABLE or CONCUR_READONLY */ protected void setResultSetConcurrency(int concurrencyFlag) { resultSetConcurrency = concurrencyFlag; } /** * Sets the result set type for (JDBC2) * * @param typeFlag SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support * SCROLL_INSENSITIVE) */ protected void setResultSetType(int typeFlag) { resultSetType = typeFlag; } /** * Sets server info (if any) * * @param info the server info message */ protected void setServerInfo(String info) { this.serverInfo = info; } /** * Returns the server info (if any), or null if none. * * @return server info created for this ResultSet */ protected String getServerInfo() { return this.serverInfo; } /** * Builds a hash between column names and their indices for fast retrieval. */ protected void buildIndexMapping() { int numFields = fields.length; columnNameToIndex = new HashMap(); fullColumnNameToIndex = new HashMap(); // We do this in reverse order, so that the 'first' column // with a given name ends up as the final mapping in the // hashtable... // // Quoting the JDBC Spec: // // "Column names used as input to getter // methods are case insensitive. When a getter method is called with a column // name and several columns have the same name, the value of the first // matching column will be returned. " // for (int i = numFields - 1; i >= 0; i--) { Integer index = new Integer(i); String columnName = fields[i].getName(); String fullColumnName = fields[i].getFullName(); if (columnName != null) { columnNameToIndex.put(columnName, index); columnNameToIndex.put(columnName.toUpperCase(), index); columnNameToIndex.put(columnName.toLowerCase(), index); } if (fullColumnName != null) { fullColumnNameToIndex.put(fullColumnName, index); fullColumnNameToIndex.put(fullColumnName.toUpperCase(), index); fullColumnNameToIndex.put(fullColumnName.toLowerCase(), index); } } // set the flag to prevent rebuilding... hasBuiltIndexMapping = true; } /** * Ensures that the result set is not closed * * @throws SQLException if the result set is closed */ protected final synchronized void checkClosed() throws SQLException { if (this.isClosed) { throw new SQLException(Messages.getString( "ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$ SQLError.SQL_STATE_GENERAL_ERROR); } } /** * Ensures that the cursor is positioned on a valid row and that the result * set is not closed * * @throws SQLException if the result set is not in a valid state for * traversal */ protected void checkRowPos() throws SQLException { checkClosed(); if (!rowData.isDynamic() && (rowData.size() == 0)) { throw new SQLException(Messages.getString( "ResultSet.Illegal_operation_on_empty_result_set"), SQLError.SQL_STATE_GENERAL_ERROR); } if (rowData.isBeforeFirst()) { throw new SQLException(Messages.getString( "ResultSet.Before_start_of_result_set_146"), SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ } if (rowData.isAfterLast()) { throw new SQLException(Messages.getString( "ResultSet.After_end_of_result_set_148"), SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$ } } // // Note, row data is linked between these two result sets // protected final ResultSet copy() throws SQLException { ResultSet rs = new ResultSet(this.catalog, this.fields, this.rowData, this.connection, this.owningStatement); return rs; } /** * Closes this ResultSet and releases resources. * * @param calledExplicitly was this called by close()? * * @throws SQLException if an error occurs */ protected void realClose(boolean calledExplicitly) throws SQLException { if (this.useUsageAdvisor) { if (!calledExplicitly && !this.isClosed) { String message = Messages.getString( "ResultSet.ResultSet_implicitly_closed_by_driver._150") //$NON-NLS-1$ + Messages.getString( "ResultSet._n_nYou_should_close_ResultSets_explicitly_from_your_code_to_free_up_resources_in_a_more_efficient_manner._151"); //$NON-NLS-1$ this.eventSink.consumeEvent(new ProfilerEvent( ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? "N/A" : this.owningStatement.currentCatalog, this.connection.getId(), (this.owningStatement == null) ? (-1) : this.owningStatement .getId(), this.resultId, System.currentTimeMillis(), 0, null, this.pointOfOrigin, message)); } if (this.rowData instanceof RowDataStatic && !isLast() && !isAfterLast() && (this.rowData.size() != 0)) { StringBuffer messageBuf = new StringBuffer(Messages.getString( "ResultSet.Possible_incomplete_traversal_of_result_set._Cursor_was_left_on_row__154")); //$NON-NLS-1$ messageBuf.append(getRow()); messageBuf.append(Messages.getString("ResultSet._of__155")); //$NON-NLS-1$ messageBuf.append(this.rowData.size()); messageBuf.append(Messages.getString( "ResultSet._rows_when_it_was_closed._156")); //$NON-NLS-1$ messageBuf.append(Messages.getString( "ResultSet._n_nYou_should_consider_re-formulating_your_query_to_return_only_the_rows_you_are_interested_in_using._157")); //$NON-NLS-1$ this.eventSink.consumeEvent(new ProfilerEvent( ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? Messages.getString("ResultSet.N/A_159") : this.owningStatement.currentCatalog, //$NON-NLS-1$ this.connection.getId(), (this.owningStatement == null) ? (-1) : this.owningStatement .getId(), this.resultId, System.currentTimeMillis(), 0, null, this.pointOfOrigin, messageBuf.toString())); } // // Report on any columns that were selected but // not referenced // if (this.columnUsed.length > 0) { StringBuffer buf = new StringBuffer(Messages.getString( "ResultSet.The_following_columns_were__160")); //$NON-NLS-1$ buf.append(Messages.getString( "ResultSet._part_of_the_SELECT_statement_for_this_result_set,_but_were_161")); //$NON-NLS-1$ buf.append(Messages.getString( "ResultSet._never_referenced___162")); //$NON-NLS-1$ boolean issueWarn = false; for (int i = 0; i < this.columnUsed.length; i++) { if (!this.columnUsed[i]) { if (!issueWarn) { issueWarn = true; } else { buf.append(", "); } buf.append(this.fields[i].getFullName()); } } if (issueWarn) { this.eventSink.consumeEvent(new ProfilerEvent( ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? "N/A" : this.owningStatement.currentCatalog, this.connection.getId(), (this.owningStatement == null) ? (-1) : this.owningStatement .getId(), 0, System.currentTimeMillis(), 0, null, this.pointOfOrigin, buf.toString())); } } } if (this.rowData != null) { this.rowData.close(); } this.rowData = null; this.defaultTimeZone = null; this.isClosed = true; } long getUpdateCount() { return this.updateCount; } long getUpdateID() { return this.updateId; } boolean reallyResult() { if (this.rowData != null) { return true; } else { return this.reallyResult; } } private final BigDecimal getBigDecimalFromString(String stringVal, int columnIndex) throws SQLException { BigDecimal bdVal; if (stringVal != null) { if (stringVal.length() == 0) { bdVal = new BigDecimal(0); return bdVal; } try { bdVal = new BigDecimal(stringVal); return bdVal; } catch (NumberFormatException ex) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_BigDecimal____166") //$NON-NLS-1$ + stringVal + Messages.getString("ResultSet.___in_column__167") + columnIndex + "(" //$NON-NLS-1$ + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } return null; } private final BigDecimal getBigDecimalFromString(String stringVal, int scale, int columnIndex) throws SQLException { BigDecimal val; if (stringVal != null) { if (stringVal.length() == 0) { val = new BigDecimal(0); return val.setScale(scale); } val = new BigDecimal(stringVal); return val.setScale(scale); } else { return null; } } private final InputStream getBinaryStreamFromString(String stringVal, int columnIndex) throws SQLException { if (stringVal != null) { byte[] b = StringUtils.getBytes(stringVal, this.connection.getEncoding(), this.connection.getServerCharacterEncoding(), this.connection.parserKnowsUnicode()); return new ByteArrayInputStream(b); } else { return null; } } private final java.sql.Blob getBlobFromString(String stringVal, int columnIndex) throws SQLException { if (!this.connection.getEmulateLocators()) { return new Blob(StringUtils.getBytes(stringVal, this.connection.getEncoding(), this.connection.getServerCharacterEncoding(), this.connection.parserKnowsUnicode())); } else { return new BlobFromLocator(this, columnIndex); } } private final boolean getBooleanFromString(String stringVal, int columnIndex) throws SQLException { if ((stringVal != null) && (stringVal.length() > 0)) { int c = Character.toLowerCase(stringVal.charAt(0)); return ((c == 't') || (c == 'y') || (c == '1') || stringVal.equals("-1")); } return false; } private final byte getByteFromString(String stringVal, int columnIndex) throws SQLException { try { int decimalIndex = stringVal.indexOf("."); // Strip off the decimals if (decimalIndex != -1) { stringVal = stringVal.substring(0, decimalIndex); } return Byte.parseByte(stringVal); } catch (NumberFormatException NFE) { throw new SQLException(Messages.getString("ResultSet.Value____173") + stringVal //$NON-NLS-1$ + Messages.getString( "ResultSet.___is_out_of_range_[-127,127]_174"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private final byte[] getBytesFromString(String stringVal, int columnIndex) throws SQLException { if (stringVal != null) { return StringUtils.getBytes(stringVal, this.connection.getEncoding(), this.connection.getServerCharacterEncoding(), this.connection.parserKnowsUnicode()); } else { return null; } } private final java.io.Reader getCharacterStreamFromString( String stringVal, int columnIndex) throws SQLException { if (stringVal != null) { return new StringReader(stringVal); } else { return null; } } private final java.sql.Clob getClobFromString(String stringVal, int columnIndex) throws SQLException { return new com.mysql.jdbc.Clob(stringVal); } private final java.sql.Date getDateFromString(String stringVal, int columnIndex) throws SQLException { int year = 0; int month = 0; int day = 0; wasNullFlag = false; try { if (stringVal == null) { wasNullFlag = true; return null; } else if (stringVal.equals("0000-00-00") || stringVal.equals("0000-00-00 00:00:00") || stringVal.equals("00000000000000") || stringVal.equals("0")) { wasNullFlag = true; return null; } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { // Convert from TIMESTAMP switch (stringVal.length()) { case 21: case 19: { // java.sql.Timestamp format year = Integer.parseInt(stringVal.substring(0, 4)); month = Integer.parseInt(stringVal.substring(5, 7)); day = Integer.parseInt(stringVal.substring(8, 10)); return fastDateCreate(null, year, month, day); } case 14: case 8: { year = Integer.parseInt(stringVal.substring(0, 4)); month = Integer.parseInt(stringVal.substring(4, 6)); day = Integer.parseInt(stringVal.substring(6, 8)); return fastDateCreate(null, year, month, day); } case 12: case 10: case 6: { year = Integer.parseInt(stringVal.substring(0, 2)); if (year <= 69) { year = year + 100; } month = Integer.parseInt(stringVal.substring(2, 4)); day = Integer.parseInt(stringVal.substring(4, 6)); return fastDateCreate(null, year + 1900, month, day); } case 4: { year = Integer.parseInt(stringVal.substring(0, 4)); if (year <= 69) { year = year + 100; } month = Integer.parseInt(stringVal.substring(2, 4)); return fastDateCreate(null, year + 1900, month, 1); } case 2: { year = Integer.parseInt(stringVal.substring(0, 2)); if (year <= 69) { year = year + 100; } return fastDateCreate(null, year + 1900, 1, 1); } default: throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_Date", new Object[] { stringVal, new Integer(columnIndex) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } /* endswitch */ } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { year = Integer.parseInt(stringVal.substring(0, 4)); return fastDateCreate(null, year, 1, 1); } else { if (stringVal.length() < 10) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_Date", new Object[] { stringVal, new Integer(columnIndex) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } year = Integer.parseInt(stringVal.substring(0, 4)); month = Integer.parseInt(stringVal.substring(5, 7)); day = Integer.parseInt(stringVal.substring(8, 10)); } return fastDateCreate(null, year, month, day); } catch (SQLException sqlEx) { throw sqlEx; // don't re-wrap } catch (Exception e) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_Date", new Object[] { stringVal, new Integer(columnIndex) }), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private final double getDoubleFromString(String stringVal, int columnIndex) throws SQLException { return getDoubleInternal(stringVal, columnIndex); } private final float getFloatFromString(String val, int columnIndex) throws SQLException { try { if ((val != null) && (val.length() != 0)) { float f = Float.parseFloat(val); return f; } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (float) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getFloat()_-____200") + val //$NON-NLS-1$ + Messages.getString("ResultSet.___in_column__201") + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private final int getIntFromString(String val, int columnIndex) throws SQLException { try { if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) { return Integer.parseInt(val); } else { // Convert floating point return (int) (Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (int) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getInt()_-____206") + val //$NON-NLS-1$ + Messages.getString("ResultSet.___in_column__207") + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private final long getLongFromString(String val, int columnIndex) throws SQLException { try { if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) { return Long.parseLong(val); } else { // Convert floating point return Double.doubleToLongBits(Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (long) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getLong()_-____211") + val //$NON-NLS-1$ + Messages.getString("ResultSet.___in_column__212") + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private void setDefaultTimeZone(TimeZone defaultTimeZone) { this.defaultTimeZone = defaultTimeZone; } private synchronized TimeZone getDefaultTimeZone() { if (this.defaultTimeZone == null) { this.defaultTimeZone = TimeZone.getDefault(); } return this.defaultTimeZone; } private Time getNativeTime(int columnIndex, TimeZone tz) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } int mysqlType = this.fields[columnIndex - 1].getMysqlType(); if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) { Time time = (java.sql.Time) this.thisRow[columnIndex - 1]; Time adjustedTime = TimeUtil.changeTimezone(this.connection, time, this.connection.getServerTimezoneTZ(), tz); return adjustedTime; } else { String strTime = getNativeString(columnIndex); return getTimeFromString(strTime, columnIndex, tz); } } private Timestamp getNativeTimestamp(int columnIndex, TimeZone tz) throws SQLException { checkRowPos(); checkColumnBounds(columnIndex); if(checkNull(columnIndex)) { return null; } int mysqlType = this.fields[columnIndex - 1].getMysqlType(); switch (mysqlType) { case MysqlDefs.FIELD_TYPE_DATETIME: case MysqlDefs.FIELD_TYPE_TIMESTAMP: Timestamp ts = (java.sql.Timestamp) this.thisRow[columnIndex - 1]; Timestamp adjustedTs = TimeUtil.changeTimezone(this.connection, ts, this.connection.getServerTimezoneTZ(), tz); return adjustedTs; default: String strTimestamp = getNativeString(columnIndex); return getTimestampFromString(columnIndex, strTimestamp, tz); } } private final short getShortFromString(String val, int columnIndex) throws SQLException { try { if ((val != null) && (val.length() != 0)) { if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) { return Short.parseShort(val); } else { // Convert floating point return (short) (Double.parseDouble(val)); } } else { return 0; } } catch (NumberFormatException nfe) { try { // To do: Warn of over/underflow??? return (short) Double.parseDouble(val); } catch (NumberFormatException newNfe) { ; // ignore, it's not a number } throw new SQLException(Messages.getString( "ResultSet.Invalid_value_for_getShort()_-____217") + val //$NON-NLS-1$ + Messages.getString("ResultSet.___in_column__218") + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$ } } private Time getTimeFromString(String timeAsString, int columnIndex, TimeZone tz) throws SQLException { int hr = 0; int min = 0; int sec = 0; wasNullFlag = false; try { if (timeAsString == null) { wasNullFlag = true; return null; } else if (timeAsString.equals("0000-00-00") || timeAsString.equals("0000-00-00 00:00:00") || timeAsString.equals("00000000000000")) { wasNullFlag = true; return null; } Field timeColField = fields[columnIndex - 1]; if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) { // It's a timestamp int length = timeAsString.length(); switch (length) { case 14: case 12: { hr = Integer.parseInt(timeAsString.substring(length - 6, length - 4)); min = Integer.parseInt(timeAsString.substring(length - 4, length - 2)); sec = Integer.parseInt(timeAsString.substring(length - 2, length)); } break; case 10: { hr = Integer.parseInt(timeAsString.substring(6, 8)); min = Integer.parseInt(timeAsString.substring(8, 10)); sec = 0; } break; default: throw new SQLException(Messages.getString( "ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$ + columnIndex + "(" + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } /* endswitch */ SQLWarning precisionLost = new SQLWarning(Messages.getString( "ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$ + columnIndex + "(" + fields[columnIndex - 1] + ")."); if (warningChain == null) { warningChain = precisionLost; } else { warningChain.setNextWarning(precisionLost); } } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) { hr = Integer.parseInt(timeAsString.substring(11, 13)); min = Integer.parseInt(timeAsString.substring(14, 16)); sec = Integer.parseInt(timeAsString.substring(17, 19)); SQLWarning precisionLost = new SQLWarning(Messages.getString( "ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$ + columnIndex + "(" + fields[columnIndex - 1] + ")."); if (warningChain == null) { warningChain = precisionLost; } else { warningChain.setNextWarning(precisionLost); } } else { // convert a String to a Time if ((timeAsString.length() != 5) && (timeAsString.length() != 8)) { throw new SQLException(Messages.getString( "ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$ + timeAsString + Messages.getString("ResultSet.___in_column__268") + columnIndex + "(" //$NON-NLS-1$ + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } hr = Integer.parseInt(timeAsString.substring(0, 2)); min = Integer.parseInt(timeAsString.substring(3, 5)); sec = (timeAsString.length() == 5) ? 0 : Integer.parseInt(timeAsString .substring(6)); } return TimeUtil.changeTimezone(this.connection, fastTimeCreate(null, hr, min, sec), connection.getServerTimezoneTZ(), tz); } catch (Exception ex) { throw new SQLException(ex.getClass().getName(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } /** * Get the value of a column in the current row as a java.sql.Time object * in the given timezone * * @param columnIndex the first column is 1, the second is 2... * @param tz the Timezone to use * * @return the column value; null if SQL NULL * * @exception java.sql.SQLException if a database access error occurs */ private Time getTimeInternal(int columnIndex, TimeZone tz) throws java.sql.SQLException { if (this.isBinaryEncoded) { return getNativeTime(columnIndex, tz); } else { String timeAsString = getString(columnIndex); return getTimeFromString(timeAsString, columnIndex, tz); } } private Timestamp getTimestampFromString(int columnIndex, String timestampValue, TimeZone tz) throws java.sql.SQLException { wasNullFlag = false; try { if (timestampValue == null) { wasNullFlag = true; return null; } else { int length = timestampValue.length(); if ((length > 0) && (timestampValue.charAt(0) == '0') && (timestampValue.equals("0000-00-00") || timestampValue.equals("0000-00-00 00:00:00") || timestampValue.equals("00000000000000") || timestampValue.equals("0"))) { wasNullFlag = true; return null; } else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) { return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, Integer.parseInt(timestampValue.substring(0, 4)), 1, 1, 0, 0, 0, 0), connection.getServerTimezoneTZ(), tz); } else { // Convert from TIMESTAMP or DATE switch (length) { case 26: case 25: case 24: case 23: case 22: case 21: case 20: case 19: { int year = Integer.parseInt(timestampValue.substring( 0, 4)); int month = Integer.parseInt(timestampValue.substring( 5, 7)); int day = Integer.parseInt(timestampValue.substring(8, 10)); int hour = Integer.parseInt(timestampValue.substring( 11, 13)); int minutes = Integer.parseInt(timestampValue.substring( 14, 16)); int seconds = Integer.parseInt(timestampValue.substring( 17, 19)); int nanos = 0; if (length > 19) { int decimalIndex = timestampValue.lastIndexOf('.'); if (decimalIndex != -1) { if (decimalIndex + 2 <= timestampValue.length()) { nanos = Integer.parseInt(timestampValue.substring(decimalIndex + 1)); } else { throw new IllegalArgumentException(); // re-thrown further down with a // much better error message } } } return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year, month, day, hour, minutes, seconds, nanos), connection.getServerTimezoneTZ(), tz); } case 14: { int year = Integer.parseInt(timestampValue.substring( 0, 4)); int month = Integer.parseInt(timestampValue.substring( 4, 6)); int day = Integer.parseInt(timestampValue.substring(6, 8)); int hour = Integer.parseInt(timestampValue.substring( 8, 10)); int minutes = Integer.parseInt(timestampValue.substring( 10, 12)); int seconds = Integer.parseInt(timestampValue.substring( 12, 14)); return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year, month, day, hour, minutes, seconds, 0), connection.getServerTimezoneTZ(), tz); } case 12: { int year = Integer.parseInt(timestampValue.substring( 0, 2)); if (year <= 69) { year = (year + 100); } int month = Integer.parseInt(timestampValue.substring( 2, 4)); int day = Integer.parseInt(timestampValue.substring(4, 6)); int hour = Integer.parseInt(timestampValue.substring( 6, 8)); int minutes = Integer.parseInt(timestampValue.substring( 8, 10)); int seconds = Integer.parseInt(timestampValue.substring( 10, 12)); return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year + 1900, month, day, hour, minutes, seconds, 0), connection.getServerTimezoneTZ(), tz); } case 10: { int year; int month; int day; int hour; int minutes; if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) || (timestampValue.indexOf("-") != -1)) { year = Integer.parseInt(timestampValue.substring( 0, 4)); month = Integer.parseInt(timestampValue.substring( 5, 7)); day = Integer.parseInt(timestampValue.substring(8, 10)); hour = 0; minutes = 0; } else { year = Integer.parseInt(timestampValue.substring( 0, 2)); if (year <= 69) { year = (year + 100); } month = Integer.parseInt(timestampValue.substring( 2, 4)); day = Integer.parseInt(timestampValue.substring(4, 6)); hour = Integer.parseInt(timestampValue.substring( 6, 8)); minutes = Integer.parseInt(timestampValue.substring( 8, 10)); year += 1900; // two-digit year } return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year, month, day, hour, minutes, 0, 0), connection.getServerTimezoneTZ(), tz); } case 8: { int year = Integer.parseInt(timestampValue.substring( 0, 4)); int month = Integer.parseInt(timestampValue.substring( 4, 6)); int day = Integer.parseInt(timestampValue.substring(6, 8)); return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year, month, day, 0, 0, 0, 0), connection.getServerTimezoneTZ(), tz); } case 6: { int year = Integer.parseInt(timestampValue.substring( 0, 2)); if (year <= 69) { year = (year + 100); } int month = Integer.parseInt(timestampValue.substring( 2, 4)); int day = Integer.parseInt(timestampValue.substring(4, 6)); return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year + 1900, month, day, 0, 0, 0, 0), connection.getServerTimezoneTZ(), tz); } case 4: { int year = Integer.parseInt(timestampValue.substring( 0, 2)); if (year <= 69) { year = (year + 100); } int month = Integer.parseInt(timestampValue.substring( 2, 4)); return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year + 1900, month, 1, 0, 0, 0, 0), connection.getServerTimezoneTZ(), tz); } case 2: { int year = Integer.parseInt(timestampValue.substring( 0, 2)); if (year <= 69) { year = (year + 100); } return TimeUtil.changeTimezone(this.connection, fastTimestampCreate(null, year + 1900, 1, 1, 0, 0, 0, 0), connection.getServerTimezoneTZ(), tz); } default: throw new java.sql.SQLException( "Bad format for Timestamp '" + timestampValue + "' in column " + columnIndex + ".", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } } } catch (Exception e) { throw new java.sql.SQLException("Cannot convert value '" + timestampValue + "' from column " + columnIndex + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } /** * Get the value of a column in the current row as a java.sql.Timestamp * object in the given timezone * * @param columnIndex the first column is 1, the second is 2... * @param tz the timezone to use * * @return the column value; null if SQL NULL * * @exception java.sql.SQLException if a database access error occurs */ private Timestamp getTimestampInternal(int columnIndex, TimeZone tz) throws java.sql.SQLException { if (this.isBinaryEncoded) { return getNativeTimestamp(columnIndex, tz); } String timestampValue = getString(columnIndex); return getTimestampFromString(columnIndex, timestampValue, tz); } private synchronized Date fastDateCreate(Calendar cal, int year, int month, int day) { if (cal == null) { if (this.fastDateCal == null) { this.fastDateCal = new GregorianCalendar(); this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); } cal = this.fastDateCal; } return TimeUtil.fastDateCreate(cal, year, month, day); } private synchronized Time fastTimeCreate(Calendar cal, int hour, int minute, int second) { if (cal == null) { if (this.fastDateCal == null) { this.fastDateCal = new GregorianCalendar(); this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); } cal = this.fastDateCal; } return TimeUtil.fastTimeCreate(cal, hour, minute, second); } private synchronized Timestamp fastTimestampCreate(Calendar cal, int year, int month, int day, int hour, int minute, int seconds, int secondsPart) { if (cal == null) { if (this.fastDateCal == null) { this.fastDateCal = new GregorianCalendar(); this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); } cal = this.fastDateCal; } return TimeUtil.fastTimestampCreate(cal, year, month, day, hour, minute, seconds, secondsPart); } }