com.mysql.jdbc.ResultSetImpl Maven / Gradle / Ivy
Show all versions of mysql-connector-java
/*
Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
There are special exceptions to the terms and conditions of the GPL
as it is applied to this software. View the full text of the
exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
software distribution.
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 java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Constructor;
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.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeMap;
import com.mysql.jdbc.log.LogUtils;
import com.mysql.jdbc.profiler.ProfilerEvent;
import com.mysql.jdbc.profiler.ProfilerEventHandler;
/**
* 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$
*
* @see ResultSetMetaData
* @see java.sql.ResultSet
*/
public class ResultSetImpl implements ResultSetInternalMethods {
private static final Constructor JDBC_4_RS_4_ARG_CTOR;
private static final Constructor JDBC_4_RS_6_ARG_CTOR;;
private static final Constructor JDBC_4_UPD_RS_6_ARG_CTOR;
static {
if (Util.isJdbc4()) {
try {
JDBC_4_RS_4_ARG_CTOR = Class.forName(
"com.mysql.jdbc.JDBC4ResultSet").getConstructor(
new Class[] { Long.TYPE, Long.TYPE,
MySQLConnection.class,
com.mysql.jdbc.StatementImpl.class });
JDBC_4_RS_6_ARG_CTOR = Class.forName(
"com.mysql.jdbc.JDBC4ResultSet").getConstructor(
new Class[] { String.class, Field[].class,
RowData.class,
MySQLConnection.class,
com.mysql.jdbc.StatementImpl.class });
JDBC_4_UPD_RS_6_ARG_CTOR = Class.forName(
"com.mysql.jdbc.JDBC4UpdatableResultSet")
.getConstructor(
new Class[] { String.class, Field[].class,
RowData.class,
MySQLConnection.class,
com.mysql.jdbc.StatementImpl.class });
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
} else {
JDBC_4_RS_4_ARG_CTOR = null;
JDBC_4_RS_6_ARG_CTOR = null;
JDBC_4_UPD_RS_6_ARG_CTOR = null;
}
}
/**
* Epsillon between Float.MIN_VALUE and the double representation of said value.
*/
protected static final double MIN_DIFF_PREC = Float.parseFloat(Float.toString(Float.MIN_VALUE))
- Double.parseDouble(Float.toString(Float.MIN_VALUE));
/**
* Epsillon between Float.MAX_VALUE and the double representation of said value.
*/
protected static final double MAX_DIFF_PREC = Float.parseFloat(Float.toString(Float.MAX_VALUE))
- Double.parseDouble(Float.toString(Float.MAX_VALUE));
/** Counter used to generate IDs for profiling. */
static int resultCounter = 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[7] = (byte) (longVal & 0xff);
asBytes[6] = (byte) (longVal >>> 8);
asBytes[5] = (byte) (longVal >>> 16);
asBytes[4] = (byte) (longVal >>> 24);
asBytes[3] = (byte) (longVal >>> 32);
asBytes[2] = (byte) (longVal >>> 40);
asBytes[1] = (byte) (longVal >>> 48);
asBytes[0] = (byte) (longVal >>> 56);
return new BigInteger(1, asBytes);
}
/** The catalog that was in use when we were created */
protected String catalog = null;
/** Map column names (and all of their permutations) to column indices */
protected Map columnLabelToIndex = null;
/** The above map is a case-insensitive tree-map, it can be slow, this caches
* lookups into that map, because the other alternative is to create new
* object instances for every call to findColumn()....
*/
protected Map columnToIndexCache = null;
/** Keep track of columns accessed */
protected boolean[] columnUsed = null;
/** The Connection instance that created us */
protected volatile MySQLConnection connection; // The connection that
// created us
protected long connectionId = 0;
/** The current row #, -1 == before start of result set */
protected int currentRow = -1; // Cursor to current row;
TimeZone defaultTimeZone;
/** Are we in the middle of doing updates to the current row? */
protected boolean doingUpdates = false;
protected ProfilerEventHandler eventSink = null;
Calendar fastDateCal = null;
/** 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 fields for this result set */
protected Field[] fields; // The fields
/**
* 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;
/** Map of fully-specified column names to column indices */
protected Map fullColumnNameToIndex = null;
protected Map columnNameToIndex = null;
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;
protected ResultSetInternalMethods nextResultSet = null;
/** Are we on the insert row? */
protected boolean onInsertRow = false;
/** The statement that created us */
protected com.mysql.jdbc.StatementImpl owningStatement;
/**
* StackTrace generated where ResultSet was created... used when profiling
*/
protected String pointOfOrigin;
/** 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;
/** 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;
/** The actual rows */
protected RowData rowData; // The results
/**
* 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;
PreparedStatement statementUsedForFetchingRows;
/** Pointer to current row data */
protected ResultSetRow thisRow = null; // Values for current row
// 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 boolean useStrictFloatingPoint = false;
protected boolean useUsageAdvisor = false;
/** The warning chain */
protected java.sql.SQLWarning warningChain = null;
/** Did the previous value retrieval find a NULL? */
protected boolean wasNullFlag = false;
protected java.sql.Statement wrapperStatement;
protected boolean retainOwningStatement;
protected Calendar gmtCalendar = null;
protected boolean useFastDateParsing = false;
private boolean padCharsWithSpace = false;
private boolean jdbcCompliantTruncationForReads;
private boolean useFastIntParsing = true;
private boolean useColumnNamesInFindColumn;
private ExceptionInterceptor exceptionInterceptor;
final static char[] EMPTY_SPACE = new char[255];
static {
for (int i = 0; i < EMPTY_SPACE.length; i++) {
EMPTY_SPACE[i] = ' ';
}
}
protected static ResultSetImpl getInstance(long updateCount, long updateID,
MySQLConnection conn, StatementImpl creatorStmt) throws SQLException {
if (!Util.isJdbc4()) {
return new ResultSetImpl(updateCount, updateID, conn, creatorStmt);
}
return (ResultSetImpl) Util.handleNewInstance(JDBC_4_RS_4_ARG_CTOR,
new Object[] { Long.valueOf(updateCount), Long.valueOf(updateID), conn,
creatorStmt}, conn.getExceptionInterceptor());
}
/**
* Creates a result set instance that represents a query result -- We need
* to provide factory-style methods so we can support both JDBC3 (and older)
* and JDBC4 runtimes, otherwise the class verifier complains when it tries
* to load JDBC4-only interface classes that are present in JDBC4 method
* signatures.
*/
protected static ResultSetImpl getInstance(String catalog, Field[] fields,
RowData tuples, MySQLConnection conn, StatementImpl creatorStmt,
boolean isUpdatable) throws SQLException {
if (!Util.isJdbc4()) {
if (!isUpdatable) {
return new ResultSetImpl(catalog, fields, tuples, conn, creatorStmt);
}
return new UpdatableResultSet(catalog, fields, tuples, conn,
creatorStmt);
}
if (!isUpdatable) {
return (ResultSetImpl) Util
.handleNewInstance(JDBC_4_RS_6_ARG_CTOR, new Object[] {
catalog, fields, tuples, conn, creatorStmt }, conn.getExceptionInterceptor());
}
return (ResultSetImpl) Util.handleNewInstance(JDBC_4_UPD_RS_6_ARG_CTOR,
new Object[] { catalog, fields, tuples, conn, creatorStmt }, conn.getExceptionInterceptor());
}
/**
* 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 ResultSetImpl(long updateCount, long updateID, MySQLConnection conn,
StatementImpl creatorStmt) {
this.updateCount = updateCount;
this.updateId = updateID;
this.reallyResult = false;
this.fields = new Field[0];
this.connection = conn;
this.owningStatement = creatorStmt;
this.retainOwningStatement = false;
if (this.connection != null) {
this.exceptionInterceptor = this.connection.getExceptionInterceptor();
this.retainOwningStatement =
this.connection.getRetainStatementAfterResultSetClose();
this.connectionId = this.connection.getId();
this.serverTimeZoneTz = this.connection.getServerTimezoneTZ();
this.padCharsWithSpace = this.connection.getPadCharsWithSpace();
useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode();
}
}
/**
* 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 ResultSetImpl(String catalog, Field[] fields, RowData tuples,
MySQLConnection conn, StatementImpl creatorStmt) throws SQLException {
this.connection = conn;
this.retainOwningStatement = false;
if (this.connection != null) {
this.useStrictFloatingPoint = this.connection
.getStrictFloatingPoint();
this.setDefaultTimeZone(this.connection.getDefaultTimeZone());
this.connectionId = this.connection.getId();
this.useFastDateParsing = this.connection.getUseFastDateParsing();
this.profileSql = this.connection.getProfileSql();
this.retainOwningStatement =
this.connection.getRetainStatementAfterResultSetClose();
this.jdbcCompliantTruncationForReads = this.connection.getJdbcCompliantTruncationForReads();
this.useFastIntParsing = this.connection.getUseFastIntParsing();
this.serverTimeZoneTz = this.connection.getServerTimezoneTZ();
this.padCharsWithSpace = this.connection.getPadCharsWithSpace();
}
this.owningStatement = creatorStmt;
this.catalog = catalog;
this.fields = fields;
this.rowData = tuples;
this.updateCount = this.rowData.size();
if (Driver.DEBUG) {
System.out.println(Messages.getString("ResultSet.Retrieved__1")
+ this.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);
if (this.fields != null) {
initializeWithMetadata();
} // else called by Connection.initializeResultsMetadataFromCache() when cached
useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode();
this.useColumnNamesInFindColumn = this.connection.getUseColumnNamesInFindColumn();
setRowPositionValidity();
}
public void initializeWithMetadata() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
this.rowData.setMetadata(this.fields);
this.columnToIndexCache = new HashMap();
if (this.profileSql || this.connection.getUseUsageAdvisor()) {
this.columnUsed = new boolean[this.fields.length];
this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable());
this.resultId = resultCounter++;
this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
}
if (this.connection.getGatherPerformanceMetrics()) {
this.connection.incrementNumberOfResultSetsCreated();
Set tableNamesSet = new HashSet();
for (int i = 0; i < this.fields.length; i++) {
Field f = this.fields[i];
String tableName = f.getOriginalTableName();
if (tableName == null) {
tableName = f.getTableName();
}
if (tableName != null) {
if (this.connection.lowerCaseTableNames()) {
tableName = tableName.toLowerCase(); // on windows, table
// names are not case-sens.
}
tableNamesSet.add(tableName);
}
}
this.connection.reportNumberOfTablesAccessed(tableNamesSet.size());
}
}
}
private synchronized void createCalendarIfNeeded() {
if (this.fastDateCal == null) {
this.fastDateCal = new GregorianCalendar(Locale.US);
this.fastDateCal.setTimeZone(this.getDefaultTimeZone());
}
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
boolean b;
if (this.rowData.size() == 0) {
b = false;
} else {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
if (row == 0) {
beforeFirst();
b = false;
} else if (row == 1) {
b = first();
} else if (row == -1) {
b = last();
} else if (row > this.rowData.size()) {
afterLast();
b = false;
} else {
if (row < 0) {
// adjust to reflect after end of result set
int newRowPosition = this.rowData.size() + row + 1;
if (newRowPosition <= 0) {
beforeFirst();
b = false;
} else {
b = absolute(newRowPosition);
}
} else {
row--; // adjust for index difference
this.rowData.setCurrentRow(row);
this.thisRow = this.rowData.getAt(row);
b = true;
}
}
}
setRowPositionValidity();
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 {
synchronized (checkClosed().getConnectionMutex()) {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
if (this.rowData.size() != 0) {
this.rowData.afterLast();
this.thisRow = null;
}
setRowPositionValidity();
}
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
if (this.rowData.size() == 0) {
return;
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
this.rowData.beforeFirst();
this.thisRow = null;
setRowPositionValidity();
}
}
// ---------------------------------------------------------------------
// Traversal/Positioning
// ---------------------------------------------------------------------
/**
* Builds a hash between column names and their indices for fast retrieval.
*/
public void buildIndexMapping() throws SQLException {
int numFields = this.fields.length;
this.columnLabelToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER);
this.fullColumnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER);
this.columnNameToIndex = new TreeMap(String.CASE_INSENSITIVE_ORDER);
// 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 = Integer.valueOf(i);
String columnName = this.fields[i].getOriginalName();
String columnLabel = this.fields[i].getName();
String fullColumnName = this.fields[i].getFullName();
if (columnLabel != null) {
this.columnLabelToIndex.put(columnLabel, index);
}
if (fullColumnName != null) {
this.fullColumnNameToIndex.put(fullColumnName, index);
}
if (columnName != null) {
this.columnNameToIndex.put(columnName, index);
}
}
// set the flag to prevent rebuilding...
this.hasBuiltIndexMapping = true;
}
/**
* 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();
}
/**
* Ensures that the result set is not closed
*
* @throws SQLException
* if the result set is closed
*/
protected final MySQLConnection checkClosed() throws SQLException {
MySQLConnection c = this.connection;
if (c == null) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
}
return c;
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
if ((columnIndex < 1)) {
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Column_Index_out_of_range_low", new Object[] {
Integer.valueOf(columnIndex),
Integer.valueOf(this.fields.length) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
} else if ((columnIndex > this.fields.length)) {
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Column_Index_out_of_range_high", new Object[] {
Integer.valueOf(columnIndex),
Integer.valueOf(this.fields.length) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
if (this.profileSql || this.useUsageAdvisor) {
this.columnUsed[columnIndex - 1] = true;
}
}
}
/**
* 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 (!this.onValidRow) {
throw SQLError.createSQLException(this.invalidRowReason,
SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
}
}
private boolean onValidRow = false;
private String invalidRowReason = null;
protected boolean useLegacyDatetimeCode;
private TimeZone serverTimeZoneTz;
private void setRowPositionValidity() throws SQLException {
if (!this.rowData.isDynamic() && (this.rowData.size() == 0)) {
this.invalidRowReason = Messages
.getString("ResultSet.Illegal_operation_on_empty_result_set");//$NON-NLS-1$
this.onValidRow = false;
} else if (this.rowData.isBeforeFirst()) {
this.invalidRowReason = Messages
.getString("ResultSet.Before_start_of_result_set_146"); //$NON-NLS-1$
this.onValidRow = false;
} else if (this.rowData.isAfterLast()) {
this.invalidRowReason = Messages
.getString("ResultSet.After_end_of_result_set_148"); //$NON-NLS-1$
this.onValidRow = false;
} else {
this.onValidRow = true;
this.invalidRowReason = null;
}
}
/**
* We can't do this ourselves, otherwise the contract for
* Statement.getMoreResults() won't work correctly.
*/
public synchronized void clearNextResult() {
this.nextResultSet = null;
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
this.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);
}
/**
* @return
*/
private int convertToZeroWithEmptyCheck() throws SQLException {
if (this.connection.getEmptyStringsConvertToZero()) {
return 0;
}
throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor());
}
private String convertToZeroLiteralStringWithEmptyCheck()
throws SQLException {
if (this.connection.getEmptyStringsConvertToZero()) {
return "0";
}
throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor());
}
//
// Note, row data is linked between these two result sets
//
public ResultSetInternalMethods copy() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
ResultSetInternalMethods rs = ResultSetImpl.getInstance(this.catalog, this.fields, this.rowData,
this.connection, this.owningStatement, false); // note, doesn't work for updatable result sets
return rs;
}
}
public void redefineFieldsForDBMD(Field[] f) {
this.fields = f;
for (int i = 0; i < this.fields.length; i++) {
this.fields[i].setUseOldNameMetadata(true);
this.fields[i].setConnection(this.connection);
}
}
public void populateCachedMetaData(CachedResultSetMetaData cachedMetaData)
throws SQLException {
cachedMetaData.fields = this.fields;
cachedMetaData.columnNameToIndex = this.columnLabelToIndex;
cachedMetaData.fullColumnNameToIndex = this.fullColumnNameToIndex;
cachedMetaData.metadata = getMetaData();
}
public void initializeFromCachedMetaData(CachedResultSetMetaData cachedMetaData) {
this.fields = cachedMetaData.fields;
this.columnLabelToIndex = cachedMetaData.columnNameToIndex;
this.fullColumnNameToIndex = cachedMetaData.fullColumnNameToIndex;
this.hasBuiltIndexMapping = 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();
}
/**
* @param columnIndex
* @param stringVal
* @param mysqlType
* @return
* @throws SQLException
*/
private String extractStringFromNativeColumn(int columnIndex, int mysqlType)
throws SQLException {
int columnIndexMinusOne = columnIndex - 1;
this.wasNullFlag = false;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
String encoding = this.fields[columnIndexMinusOne]
.getCharacterSet();
return this.thisRow.getString(columnIndex - 1, encoding, this.connection);
}
protected Date fastDateCreate(Calendar cal, int year, int month,
int day) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (this.useLegacyDatetimeCode) {
return TimeUtil.fastDateCreate(year, month, day, cal);
}
if (cal == null) {
createCalendarIfNeeded();
cal = this.fastDateCal;
}
boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
return TimeUtil.fastDateCreate(useGmtMillis,
useGmtMillis ? getGmtCalendar() : cal,
cal, year, month, day);
}
}
protected Time fastTimeCreate(Calendar cal, int hour,
int minute, int second) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastTimeCreate(hour, minute, second, cal, getExceptionInterceptor());
}
if (cal == null) {
createCalendarIfNeeded();
cal = this.fastDateCal;
}
return TimeUtil.fastTimeCreate(cal, hour, minute, second, getExceptionInterceptor());
}
}
protected Timestamp fastTimestampCreate(Calendar cal, int year,
int month, int day, int hour, int minute, int seconds,
int secondsPart) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastTimestampCreate(cal.getTimeZone(), year, month, day, hour,
minute, seconds, secondsPart);
}
if (cal == null) {
createCalendarIfNeeded();
cal = this.fastDateCal;
}
boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
return TimeUtil.fastTimestampCreate(useGmtMillis,
useGmtMillis ? getGmtCalendar() : null,
cal, year, month, day, hour,
minute, seconds, secondsPart);
}
}
/*
/**
* Required by JDBC spec
*/
/*
protected void finalize() throws Throwable {
if (!this.isClosed) {
realClose(false);
}
}
*/
// --------------------------JDBC 2.0-----------------------------------
// ---------------------------------------------------------------------
// Getter's and Setter's
// ---------------------------------------------------------------------
/*
* [For JDBC-3.0 and older - http://java.sun.com/j2se/1.5.0/docs/api/java/sql/ResultSet.html#findColumn(java.lang.String)]
* 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
*
* [For JDBC-4.0 and newer - http://java.sun.com/javase/6/docs/api/java/sql/ResultSet.html#findColumn(java.lang.String)]
*
* Maps the given ResultSet column label to its ResultSet column index.
*
* @param columnLabel
* the label for the column specified with the SQL AS clause. If the
* SQL AS clause was not specified, then the label is the name of the column
*
* @return the column index of the given column name
*/
public int findColumn(String columnName) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
Integer index;
if (!this.hasBuiltIndexMapping) {
buildIndexMapping();
}
index = this.columnToIndexCache.get(columnName);
if (index != null) {
return index.intValue() + 1;
}
index = this.columnLabelToIndex.get(columnName);
if (index == null && this.useColumnNamesInFindColumn) {
index = this.columnNameToIndex.get(columnName);
}
if (index == null) {
index = this.fullColumnNameToIndex.get(columnName);
}
if (index != null) {
this.columnToIndexCache.put(columnName, index);
return index.intValue() + 1;
}
// Try this inefficient way, now
for (int i = 0; i < this.fields.length; i++) {
if (this.fields[i].getName().equalsIgnoreCase(columnName)) {
return i + 1;
} else if (this.fields[i].getFullName()
.equalsIgnoreCase(columnName)) {
return i + 1;
}
}
throw SQLError.createSQLException(Messages.getString("ResultSet.Column____112")
+ columnName
+ Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$
SQLError.SQL_STATE_COLUMN_NOT_FOUND, getExceptionInterceptor());
}
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
boolean b = true;
if (this.rowData.isEmpty()) {
b = false;
} else {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
this.rowData.beforeFirst();
this.thisRow = this.rowData.next();
}
setRowPositionValidity();
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 {
checkColumnBounds(i);
throw SQLError.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 {
return getArray(findColumn(colName));
}
/**
* 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);
}
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));
}
/**
* 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(
convertToZeroLiteralStringWithEmptyCheck());
return val;
}
try {
val = new BigDecimal(stringVal);
return val;
} catch (NumberFormatException ex) {
throw SQLError.createSQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
return null;
}
return getNativeBigDecimal(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
*
* @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(
convertToZeroLiteralStringWithEmptyCheck());
try {
return val.setScale(scale);
} catch (ArithmeticException ex) {
try {
return val
.setScale(scale, BigDecimal.ROUND_HALF_UP);
} catch (ArithmeticException arEx) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$
new Object[] {stringVal, Integer.valueOf(columnIndex)}),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
}
try {
val = new BigDecimal(stringVal);
} catch (NumberFormatException ex) {
if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
val = new BigDecimal(valueAsLong);
} else {
throw SQLError.createSQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { Integer.valueOf(columnIndex),
stringVal }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
try {
return val.setScale(scale);
} catch (ArithmeticException ex) {
try {
return val.setScale(scale, BigDecimal.ROUND_HALF_UP);
} catch (ArithmeticException arithEx) {
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_BigDecimal",
new Object[] { Integer.valueOf(columnIndex),
stringVal }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
}
return null;
}
return getNativeBigDecimal(columnIndex, scale);
}
/**
* 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));
}
/**
* 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);
}
private final BigDecimal getBigDecimalFromString(String stringVal,
int columnIndex, int scale) throws SQLException {
BigDecimal bdVal;
if (stringVal != null) {
if (stringVal.length() == 0) {
bdVal = new BigDecimal(convertToZeroLiteralStringWithEmptyCheck());
try {
return bdVal.setScale(scale);
} catch (ArithmeticException ex) {
try {
return bdVal.setScale(scale, BigDecimal.ROUND_HALF_UP);
} catch (ArithmeticException arEx) {
throw new SQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
}
}
}
try {
try {
return new BigDecimal(stringVal).setScale(scale);
} catch (ArithmeticException ex) {
try {
return new BigDecimal(stringVal).setScale(scale,
BigDecimal.ROUND_HALF_UP);
} catch (ArithmeticException arEx) {
throw new SQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
}
}
} catch (NumberFormatException ex) {
if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
try {
return new BigDecimal(valueAsLong).setScale(scale);
} catch (ArithmeticException arEx1) {
try {
return new BigDecimal(valueAsLong).setScale(scale,
BigDecimal.ROUND_HALF_UP);
} catch (ArithmeticException arEx2) {
throw new SQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
}
}
}
if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY &&
this.connection.getTinyInt1isBit() && this.fields[columnIndex - 1].getLength() == 1) {
return new BigDecimal(stringVal.equalsIgnoreCase("true") ? 1 : 0).setScale(scale);
}
throw new SQLException(Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
}
}
return null;
}
/**
* A column value can also be retrieved as a binary stream. 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) {
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return this.thisRow.getBinaryInputStream(columnIndexMinusOne);
}
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);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return null;
}
if (!this.connection.getEmulateLocators()) {
return new Blob(this.thisRow.getColumnValue(columnIndexMinusOne), getExceptionInterceptor());
}
return new BlobFromLocator(this, columnIndex, getExceptionInterceptor());
}
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 {
checkColumnBounds(columnIndex);
//
// MySQL 5.0 and newer have an actual BIT type,
// so we need to check for that here...
//
int columnIndexMinusOne = columnIndex - 1;
Field field = this.fields[columnIndexMinusOne];
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
return byteArrayToBoolean(columnIndexMinusOne);
}
this.wasNullFlag = false;
int sqlType = field.getSQLType();
switch (sqlType) {
case Types.BOOLEAN:
if (field.getMysqlType() == -1) { // from dbmd
String stringVal = getString(columnIndex);
return getBooleanFromString(stringVal);
}
long boolVal = getLong(columnIndex, false);
return (boolVal == -1 || boolVal > 0);
case Types.BIT:
case Types.TINYINT:
case Types.SMALLINT:
case Types.INTEGER:
case Types.BIGINT:
case Types.DECIMAL:
case Types.NUMERIC:
case Types.REAL:
case Types.FLOAT:
case Types.DOUBLE:
boolVal = getLong(columnIndex, false);
return (boolVal == -1 || boolVal > 0);
default:
if (this.connection.getPedantic()) {
// Table B-6 from JDBC spec
switch (sqlType) {
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.CLOB:
case Types.BLOB:
case Types.ARRAY:
case Types.REF:
case Types.DATALINK:
case Types.STRUCT:
case Types.JAVA_OBJECT:
throw SQLError.createSQLException("Required type conversion not allowed",
SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST, getExceptionInterceptor());
}
}
if (sqlType == Types.BINARY ||
sqlType == Types.VARBINARY ||
sqlType == Types.LONGVARBINARY ||
sqlType == Types.BLOB) {
return byteArrayToBoolean(columnIndexMinusOne);
}
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getBoolean()", columnIndex,
this.thisRow.getColumnValue(columnIndexMinusOne), this.fields[columnIndex],
new int[] {
MysqlDefs.FIELD_TYPE_BIT,
MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
String stringVal = getString(columnIndex);
return getBooleanFromString(stringVal);
}
}
private boolean byteArrayToBoolean(int columnIndexMinusOne) throws SQLException {
Object value = this.thisRow.getColumnValue(columnIndexMinusOne);
if (value == null) {
this.wasNullFlag = true;
return false;
}
this.wasNullFlag = false;
if (((byte[]) value).length == 0) {
return false;
}
byte boolVal = ((byte[]) value)[0];
if (boolVal == (byte)'1') {
return true;
} else if (boolVal == (byte)'0') {
return false;
}
return (boolVal == -1 || boolVal > 0);
}
/**
* DOCUMENT ME!
*
* @param columnName
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws SQLException
* DOCUMENT ME!
*/
public boolean getBoolean(String columnName) throws SQLException {
return getBoolean(findColumn(columnName));
}
private final boolean getBooleanFromString(String stringVal)
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;
}
/**
* 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) {
String stringVal = getString(columnIndex);
if (this.wasNullFlag || (stringVal == null)) {
return 0;
}
return getByteFromString(stringVal, columnIndex);
}
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));
}
private final byte getByteFromString(String stringVal, int columnIndex)
throws SQLException {
if (stringVal != null && stringVal.length() == 0) {
return (byte) convertToZeroWithEmptyCheck();
}
//
// JDK-6 doesn't like trailing whitespace
//
// Note this isn't a performance issue, other
// than the iteration over the string, as String.trim()
// will return a new string only if whitespace is present
//
if (stringVal == null) {
return 0;
}
stringVal = stringVal.trim();
try {
int decimalIndex = stringVal.indexOf(".");
if (decimalIndex != -1) {
double valueAsDouble = Double.parseDouble(stringVal);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Byte.MIN_VALUE
|| valueAsDouble > Byte.MAX_VALUE) {
throwRangeException(stringVal, columnIndex,
Types.TINYINT);
}
}
return (byte) valueAsDouble;
}
long valueAsLong = Long.parseLong(stringVal);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsLong < Byte.MIN_VALUE
|| valueAsLong > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex, Types.TINYINT);
}
}
return (byte) valueAsLong;
} catch (NumberFormatException NFE) {
throw SQLError.createSQLException(
Messages.getString("ResultSet.Value____173")
+ stringVal //$NON-NLS-1$
+ Messages
.getString("ResultSet.___is_out_of_range_[-127,127]_174"),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
/**
* 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 {
return getBytes(columnIndex, false);
}
protected byte[] getBytes(int columnIndex, boolean noConversion)
throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return null;
}
return this.thisRow.getColumnValue(columnIndexMinusOne);
}
return getNativeBytes(columnIndex, noConversion);
}
/**
* DOCUMENT ME!
*
* @param columnName
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws SQLException
* DOCUMENT ME!
*/
public byte[] getBytes(String columnName) throws SQLException {
return getBytes(findColumn(columnName));
}
private final byte[] getBytesFromString(String stringVal)
throws SQLException {
if (stringVal != null) {
return StringUtils.getBytes(stringVal, this.connection
.getEncoding(), this.connection
.getServerCharacterEncoding(), this.connection
.parserKnowsUnicode(),
this.connection, getExceptionInterceptor());
}
return null;
}
public int getBytesSize() throws SQLException {
RowData localRowData = this.rowData;
checkClosed();
if (localRowData instanceof RowDataStatic) {
int bytesSize = 0;
int numRows = localRowData.size();
for (int i = 0; i < numRows; i++) {
bytesSize += localRowData.getAt(i).getBytesSize();
}
return bytesSize;
}
return -1;
}
/**
* Optimization to only use one calendar per-session, or calculate it for
* each call, depending on user configuration
*/
protected Calendar getCalendarInstanceForSessionOrNew() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (this.connection != null) {
return this.connection.getCalendarInstanceForSessionOrNew();
}
// punt, no connection around
return new GregorianCalendar();
}
}
/**
* 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) {
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return this.thisRow.getReader(columnIndexMinusOne);
}
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));
}
private final java.io.Reader getCharacterStreamFromString(String stringVal)
throws SQLException {
if (stringVal != null) {
return new StringReader(stringVal);
}
return null;
}
/**
* 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) {
String asString = getStringForClob(i);
if (asString == null) {
return null;
}
return new com.mysql.jdbc.Clob(asString, getExceptionInterceptor());
}
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));
}
private final java.sql.Clob getClobFromString(String stringVal) throws SQLException {
return new com.mysql.jdbc.Clob(stringVal, getExceptionInterceptor());
}
/**
* 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 SQLError.createSQLException(Messages
.getString("ResultSet.Positioned_Update_not_supported"),
SQLError.SQL_STATE_DRIVER_NOT_CAPABLE, getExceptionInterceptor()); //$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);
}
/**
* 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);
}
if (!this.useFastDateParsing) {
String stringVal = getStringInternal(columnIndex, false);
if (stringVal == null) {
return null;
}
return getDateFromString(stringVal, columnIndex, cal);
}
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
Date tmpDate = this.thisRow.getDateFast(columnIndexMinusOne, this.connection, this, cal);
if ((this.thisRow.isNull(columnIndexMinusOne))
|| (tmpDate == null)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return tmpDate;
}
/**
* 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));
}
/**
* 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);
}
private final java.sql.Date getDateFromString(String stringVal,
int columnIndex, Calendar targetCalendar) throws SQLException {
int year = 0;
int month = 0;
int day = 0;
try {
this.wasNullFlag = false;
if (stringVal == null) {
this.wasNullFlag = true;
return null;
}
//
// JDK-6 doesn't like trailing whitespace
//
// Note this isn't a performance issue, other
// than the iteration over the string, as String.trim()
// will return a new string only if whitespace is present
//
stringVal = stringVal.trim();
if (stringVal.equals("0") || stringVal.equals("0000-00-00")
|| stringVal.equals("0000-00-00 00:00:00")
|| stringVal.equals("00000000000000")
|| stringVal.equals("0")) {
if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
.equals(this.connection.getZeroDateTimeBehavior())) {
this.wasNullFlag = true;
return null;
} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
.equals(this.connection.getZeroDateTimeBehavior())) {
throw SQLError.createSQLException("Value '" + stringVal
+ "' can not be represented as java.sql.Date",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
// We're left with the case of 'round' to a date Java _can_
// represent, which is '0001-01-01'.
return fastDateCreate(targetCalendar, 1, 1, 1);
} else if (this.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(targetCalendar, 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(targetCalendar, 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(targetCalendar, 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(targetCalendar, year + 1900, month, 1);
}
case 2: {
year = Integer.parseInt(stringVal.substring(0, 2));
if (year <= 69) {
year = year + 100;
}
return fastDateCreate(targetCalendar, year + 1900, 1, 1);
}
default:
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_Date", new Object[] {
stringVal, Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
} /* endswitch */
} else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
if (stringVal.length() == 2 || stringVal.length() == 1) {
year = Integer.parseInt(stringVal);
if (year <= 69) {
year = year + 100;
}
year += 1900;
} else {
year = Integer.parseInt(stringVal.substring(0, 4));
}
return fastDateCreate(targetCalendar, year, 1, 1);
} else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
return fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH
} else {
if (stringVal.length() < 10) {
if (stringVal.length() == 8) {
return fastDateCreate(targetCalendar, 1970, 1, 1); // Return EPOCH for TIME
}
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_Date", new Object[] {
stringVal, Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
if (stringVal.length() != 18) {
year = Integer.parseInt(stringVal.substring(0, 4));
month = Integer.parseInt(stringVal.substring(5, 7));
day = Integer.parseInt(stringVal.substring(8, 10));
} else {
// JDK-1.3 timestamp format, not real easy to parse positionally :p
StringTokenizer st = new StringTokenizer(stringVal, "- ");
year = Integer.parseInt(st.nextToken());
month = Integer.parseInt(st.nextToken());
day = Integer.parseInt(st.nextToken());
}
}
return fastDateCreate(targetCalendar, year, month, day);
} catch (SQLException sqlEx) {
throw sqlEx; // don't re-wrap
} catch (Exception e) {
SQLException sqlEx = SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_Date", new Object[] { stringVal,
Integer.valueOf(columnIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
sqlEx.initCause(e);
throw sqlEx;
}
}
private TimeZone getDefaultTimeZone() {
if (!this.useLegacyDatetimeCode && this.connection != null) {
return this.serverTimeZoneTz;
}
return this.connection.getDefaultTimeZone();
}
/**
* 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);
}
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));
}
private final double getDoubleFromString(String stringVal, int columnIndex)
throws SQLException {
return getDoubleInternal(stringVal, columnIndex);
}
/**
* 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)) {
return 0;
}
if (stringVal.length() == 0) {
return convertToZeroWithEmptyCheck();
}
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) {
if (this.fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex);
return valueAsLong;
}
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_number", new Object[] {
stringVal, Integer.valueOf(colIndex) }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
return this.fetchDirection;
}
}
/**
* 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 {
synchronized (checkClosed().getConnectionMutex()) {
return this.fetchSize;
}
}
/**
* Returns the first character of the query that this result set was created
* from.
*
* @return the first character of the query...uppercased
*/
public char getFirstCharOfQuery() {
try {
synchronized (checkClosed().getConnectionMutex()) {
return this.firstCharOfQuery;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve interface
}
}
/**
* 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) {
String val = null;
val = getString(columnIndex);
return getFloatFromString(val, columnIndex);
}
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));
}
private final float getFloatFromString(String val, int columnIndex)
throws SQLException {
try {
if ((val != null)) {
if (val.length() == 0) {
return convertToZeroWithEmptyCheck();
}
float f = Float.parseFloat(val);
if (this.jdbcCompliantTruncationForReads) {
if (f == Float.MIN_VALUE || f == Float.MAX_VALUE) {
double valAsDouble = Double.parseDouble(val);
// Straight comparison is not reliable when at
// absolute endpoints of Float.MIN_VALUE or
// Float.MAX_VALUE, so use epsillons with DOUBLEs
if ((valAsDouble < Float.MIN_VALUE - MIN_DIFF_PREC)
|| (valAsDouble > Float.MAX_VALUE - MAX_DIFF_PREC)) {
throwRangeException(String.valueOf(valAsDouble), columnIndex,
Types.FLOAT);
}
}
}
return f;
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
Double valueAsDouble = new Double(val);
float valueAsFloat = valueAsDouble.floatValue();
if (this.jdbcCompliantTruncationForReads) {
if (this.jdbcCompliantTruncationForReads &&
valueAsFloat == Float.NEGATIVE_INFINITY ||
valueAsFloat == Float.POSITIVE_INFINITY) {
throwRangeException(valueAsDouble.toString(),
columnIndex, Types.FLOAT);
}
}
return valueAsFloat;
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getFloat()_-____200")
+ val //$NON-NLS-1$
+ Messages.getString("ResultSet.___in_column__201")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
/**
* 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 {
checkRowPos();
if (!this.isBinaryEncoded) {
int columnIndexMinusOne = columnIndex - 1;
if (this.useFastIntParsing) {
checkColumnBounds(columnIndex);
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return 0;
}
if (this.thisRow.length(columnIndexMinusOne) == 0) {
return convertToZeroWithEmptyCheck();
}
boolean needsFullParse = this.thisRow
.isFloatingPointNumber(columnIndexMinusOne);
if (!needsFullParse) {
try {
return getIntWithOverflowCheck(columnIndexMinusOne);
} catch (NumberFormatException nfe) {
try {
return parseIntAsDouble(columnIndex, this.thisRow
.getString(columnIndexMinusOne,
this.fields[columnIndexMinusOne]
.getCharacterSet(),
this.connection));
} catch (NumberFormatException newNfe) {
// ignore, it's not a number
}
if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
if (this.connection
.getJdbcCompliantTruncationForReads()
&& (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
throwRangeException(
String.valueOf(valueAsLong),
columnIndex, Types.INTEGER);
}
return (int) valueAsLong;
}
throw SQLError
.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getInt()_-____74")
+ this.thisRow
.getString(
columnIndexMinusOne,
this.fields[columnIndexMinusOne]
.getCharacterSet(),
this.connection) //$NON-NLS-1$
+ "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
}
String val = null;
try {
val = getString(columnIndex);
if ((val != null)) {
if (val.length() == 0) {
return convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
&& (val.indexOf(".") == -1)) {
int intVal = Integer.parseInt(val);
checkForIntegerTruncation(columnIndexMinusOne, null, intVal);
return intVal;
}
// Convert floating point
int intVal = parseIntAsDouble(columnIndex, val);
checkForIntegerTruncation(columnIndex, null, intVal);
return intVal;
}
return 0;
} catch (NumberFormatException nfe) {
try {
return parseIntAsDouble(columnIndex, val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
if (this.jdbcCompliantTruncationForReads
&& (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex, Types.INTEGER);
}
return (int) valueAsLong;
}
throw SQLError
.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getInt()_-____74")
+ val //$NON-NLS-1$
+ "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
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));
}
private final int getIntFromString(String val, int columnIndex)
throws SQLException {
try {
if ((val != null)) {
if (val.length() == 0) {
return convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
&& (val.indexOf(".") == -1)) {
//
// JDK-6 doesn't like trailing whitespace
//
// Note this isn't a performance issue, other
// than the iteration over the string, as String.trim()
// will return a new string only if whitespace is present
//
val = val.trim();
int valueAsInt = Integer.parseInt(val);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsInt == Integer.MIN_VALUE
|| valueAsInt == Integer.MAX_VALUE) {
long valueAsLong = Long.parseLong(val);
if (valueAsLong < Integer.MIN_VALUE
|| valueAsLong > Integer.MAX_VALUE) {
throwRangeException(
String.valueOf(valueAsLong),
columnIndex, Types.INTEGER);
}
}
}
return valueAsInt;
}
// Convert floating point
double valueAsDouble = Double.parseDouble(val);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex, Types.INTEGER);
}
}
return (int) valueAsDouble;
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
double valueAsDouble = Double.parseDouble(val);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex, Types.INTEGER);
}
}
return (int) valueAsDouble;
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw SQLError.createSQLException(Messages
.getString("ResultSet.Invalid_value_for_getInt()_-____206")
+ val //$NON-NLS-1$
+ Messages.getString("ResultSet.___in_column__207")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
/**
* 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 {
return getLong(columnIndex, true);
}
private long getLong(int columnIndex, boolean overflowCheck) throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
int columnIndexMinusOne = columnIndex - 1;
if (this.useFastIntParsing) {
checkColumnBounds(columnIndex);
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return 0;
}
if (this.thisRow.length(columnIndexMinusOne) == 0) {
return convertToZeroWithEmptyCheck();
}
boolean needsFullParse = this.thisRow.isFloatingPointNumber(columnIndexMinusOne);
if (!needsFullParse) {
try {
return getLongWithOverflowCheck(columnIndexMinusOne, overflowCheck);
} catch (NumberFormatException nfe) {
try {
// To do: Warn of over/underflow???
return parseLongAsDouble(columnIndexMinusOne, this.thisRow
.getString(columnIndexMinusOne,
this.fields[columnIndexMinusOne]
.getCharacterSet(),
this.connection));
} catch (NumberFormatException newNfe) {
// ; // ignore, it's not a number
}
if (this.fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
return getNumericRepresentationOfSQLBitType(columnIndex);
}
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getLong()_-____79")
+ this.thisRow
.getString(columnIndexMinusOne,
this.fields[columnIndexMinusOne]
.getCharacterSet(),
this.connection) //$NON-NLS-1$
+ "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
}
String val = null;
try {
val = getString(columnIndex);
if ((val != null)) {
if (val.length() == 0) {
return convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
return parseLongWithOverflowCheck(columnIndexMinusOne, null,
val, overflowCheck);
}
// Convert floating point
return parseLongAsDouble(columnIndexMinusOne, val);
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
return parseLongAsDouble(columnIndexMinusOne, val);
} catch (NumberFormatException newNfe) {
// ; // ignore, it's not a number
}
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getLong()_-____79")
+ val //$NON-NLS-1$
+ "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
return getNativeLong(columnIndex, overflowCheck, true);
}
/**
* DOCUMENT ME!
*
* @param columnName
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws SQLException
* DOCUMENT ME!
*/
public long getLong(String columnName) throws SQLException {
return getLong(findColumn(columnName));
}
private final long getLongFromString(String val, int columnIndexZeroBased)
throws SQLException {
try {
if ((val != null)) {
if (val.length() == 0) {
return convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
return parseLongWithOverflowCheck(columnIndexZeroBased, null, val, true);
}
// Convert floating point
return parseLongAsDouble(columnIndexZeroBased, val);
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
// To do: Warn of over/underflow???
return parseLongAsDouble(columnIndexZeroBased, val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Invalid_value_for_getLong()_-____211")
+ val //$NON-NLS-1$
+ Messages.getString("ResultSet.___in_column__212")
+ (columnIndexZeroBased + 1), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
/**
* 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 {
checkClosed();
return new com.mysql.jdbc.ResultSetMetaData(fields, connection.getUseOldAliasMetadataBehavior(),
connection.getYearIsDateType(), getExceptionInterceptor());
}
/**
* 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 SQLError.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);
}
/**
* 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 {
checkColumnBounds(columnIndex);
int scale = this.fields[columnIndex - 1].getDecimals();
return getNativeBigDecimal(columnIndex, scale);
}
/**
* 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 {
checkColumnBounds(columnIndex);
String stringVal = null;
Field f = this.fields[columnIndex - 1];
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
switch (f.getSQLType()) {
case Types.DECIMAL:
case Types.NUMERIC:
stringVal = StringUtils
.toAsciiString((byte[]) value);
break;
default:
stringVal = getNativeString(columnIndex);
}
return getBigDecimalFromString(stringVal, columnIndex, scale);
}
/**
* A column value can also be retrieved as a binary stream. 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();
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
switch (this.fields[columnIndexMinusOne].getSQLType()) {
case Types.BIT:
case Types.BINARY:
case Types.VARBINARY:
case Types.BLOB:
case Types.LONGVARBINARY:
return this.thisRow.getBinaryInputStream(columnIndexMinusOne);
}
byte[] b = getNativeBytes(columnIndex, false);
if (b != null) {
return new ByteArrayInputStream(b);
}
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);
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
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[]) value;
break;
default:
dataAsBytes = getNativeBytes(columnIndex, false);
}
if (!this.connection.getEmulateLocators()) {
return new Blob(dataAsBytes, getExceptionInterceptor());
}
return new BlobFromLocator(this, columnIndex, getExceptionInterceptor());
}
public static boolean arraysEqual(byte[] left, byte[] right) {
if (left == null) {
return right == null;
}
if (right == null) {
return false;
}
if (left.length != right.length) {
return false;
}
for (int i = 0; i < left.length; i++) {
if (left[i] != right[i]) {
return false;
}
}
return true;
}
/**
* 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 {
return getNativeByte(columnIndex, true);
}
protected byte getNativeByte(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
columnIndex--;
Field field = this.fields[columnIndex];
switch (field.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_BIT:
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
(valueAsLong < Byte.MIN_VALUE
|| valueAsLong > Byte.MAX_VALUE)) {
throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
Types.TINYINT);
}
return (byte)valueAsLong;
case MysqlDefs.FIELD_TYPE_TINY:
byte valueAsByte = ((byte[]) value)[0];
if (!field.isUnsigned()) {
return valueAsByte;
}
short valueAsShort = (valueAsByte >= 0) ?
valueAsByte : (short)(valueAsByte + (short)256);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsShort > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsShort),
columnIndex + 1, Types.TINYINT);
}
}
return (byte)valueAsShort;
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
valueAsShort = getNativeShort(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsShort < Byte.MIN_VALUE
|| valueAsShort > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsShort),
columnIndex + 1, Types.TINYINT);
}
}
return (byte) valueAsShort;
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
int valueAsInt = getNativeInt(columnIndex + 1, false);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsInt < Byte.MIN_VALUE || valueAsInt > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsInt),
columnIndex + 1, Types.TINYINT);
}
}
return (byte) valueAsInt;
case MysqlDefs.FIELD_TYPE_FLOAT:
float valueAsFloat = getNativeFloat(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsFloat < Byte.MIN_VALUE
|| valueAsFloat > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsFloat),
columnIndex + 1, Types.TINYINT);
}
}
return (byte) valueAsFloat;
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Byte.MIN_VALUE
|| valueAsDouble > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.TINYINT);
}
}
return (byte) valueAsDouble;
case MysqlDefs.FIELD_TYPE_LONGLONG:
valueAsLong = getNativeLong(columnIndex + 1, false, true);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsLong < Byte.MIN_VALUE
|| valueAsLong > Byte.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex + 1, Types.TINYINT);
}
}
return (byte) valueAsLong;
default:
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getByte()", columnIndex,
this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getByteFromString(getNativeString(columnIndex + 1),
columnIndex + 1);
}
}
/**
* 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, boolean noConversion)
throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return null;
}
Field field = this.fields[columnIndex - 1];
int mysqlType = field.getMysqlType();
// Workaround for emulated locators in servers > 4.1,
// as server returns SUBSTRING(blob) as STRING type...
if (noConversion) {
mysqlType = MysqlDefs.FIELD_TYPE_BLOB;
}
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:
case MysqlDefs.FIELD_TYPE_BIT:
return (byte[]) value;
case MysqlDefs.FIELD_TYPE_STRING:
case MysqlDefs.FIELD_TYPE_VARCHAR:
case MysqlDefs.FIELD_TYPE_VAR_STRING:
if (value instanceof byte[]) {
return (byte[]) value;
}
// fallthrough
default:
int sqlType = field.getSQLType();
if (sqlType == Types.VARBINARY || sqlType == Types.BINARY) {
return (byte[]) value;
}
return getBytesFromString(getNativeString(columnIndex));
}
}
/**
* 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 {
int columnIndexMinusOne = columnIndex - 1;
switch (this.fields[columnIndexMinusOne].getSQLType()) {
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.CLOB:
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return this.thisRow.getReader(columnIndexMinusOne);
}
String asString = getStringForClob(columnIndex);
if (asString == null) {
return null;
}
return getCharacterStreamFromString(asString);
}
/**
* 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 = getStringForClob(columnIndex);
if (stringVal == null) {
return null;
}
return getClobFromString(stringVal);
}
private String getNativeConvertToString(int columnIndex,
Field field)
throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
int sqlType = field.getSQLType();
int mysqlType = field.getMysqlType();
switch (sqlType) {
case Types.BIT:
return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
case Types.BOOLEAN:
boolean booleanVal = getBoolean(columnIndex);
if (this.wasNullFlag) {
return null;
}
return String.valueOf(booleanVal);
case Types.TINYINT:
byte tinyintVal = getNativeByte(columnIndex, false);
if (this.wasNullFlag) {
return null;
}
if (!field.isUnsigned() || tinyintVal >= 0) {
return String.valueOf(tinyintVal);
}
short unsignedTinyVal = (short) (tinyintVal & 0xff);
return String.valueOf(unsignedTinyVal);
case Types.SMALLINT:
int intVal = getNativeInt(columnIndex, false);
if (this.wasNullFlag) {
return null;
}
if (!field.isUnsigned() || intVal >= 0) {
return String.valueOf(intVal);
}
intVal = intVal & 0xffff;
return String.valueOf(intVal);
case Types.INTEGER:
intVal = getNativeInt(columnIndex, false);
if (this.wasNullFlag) {
return null;
}
if (!field.isUnsigned() || intVal >= 0
|| field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
return String.valueOf(intVal);
}
long longVal = intVal & 0xffffffffL;
return String.valueOf(longVal);
case Types.BIGINT:
if (!field.isUnsigned()) {
longVal = getNativeLong(columnIndex, false, true);
if (this.wasNullFlag) {
return null;
}
return String.valueOf(longVal);
}
longVal = getNativeLong(columnIndex, false, false);
if (this.wasNullFlag) {
return null;
}
return String.valueOf(convertLongToUlong(longVal));
case Types.REAL:
float floatVal = getNativeFloat(columnIndex);
if (this.wasNullFlag) {
return null;
}
return String.valueOf(floatVal);
case Types.FLOAT:
case Types.DOUBLE:
double doubleVal = getNativeDouble(columnIndex);
if (this.wasNullFlag) {
return null;
}
return String.valueOf(doubleVal);
case Types.DECIMAL:
case Types.NUMERIC:
String stringVal = StringUtils
.toAsciiString(this.thisRow.getColumnValue(columnIndex - 1));
BigDecimal val;
if (stringVal != null) {
this.wasNullFlag = false;
if (stringVal.length() == 0) {
val = new BigDecimal(0);
return val.toString();
}
try {
val = new BigDecimal(stringVal);
} catch (NumberFormatException ex) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Bad_format_for_BigDecimal",
new Object[] {stringVal, Integer.valueOf(columnIndex)}),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
return val.toString();
}
this.wasNullFlag = true;
return null;
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
return extractStringFromNativeColumn(columnIndex, mysqlType);
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
if (!field.isBlob()) {
return extractStringFromNativeColumn(columnIndex, mysqlType);
} else if (!field.isBinary()) {
return extractStringFromNativeColumn(columnIndex, mysqlType);
} 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 SQLError.createSQLException(
Messages
.getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
+ cnfe.toString()
+ Messages
.getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor()); //$NON-NLS-1$
} catch (IOException ex) {
obj = data; // not serialized?
}
}
return obj.toString();
}
return extractStringFromNativeColumn(columnIndex, mysqlType);
}
case Types.DATE:
// The YEAR datatype needs to be handled differently here.
if (mysqlType == MysqlDefs.FIELD_TYPE_YEAR) {
short shortVal = getNativeShort(columnIndex);
if (!this.connection.getYearIsDateType()) {
if (this.wasNullFlag) {
return null;
}
return String.valueOf(shortVal);
}
if (field.getLength() == 2) {
if (shortVal <= 69) {
shortVal = (short) (shortVal + 100);
}
shortVal += 1900;
}
return fastDateCreate(null, shortVal, 1, 1).toString();
}
if (this.connection.getNoDatetimeStringSync()) {
byte[] asBytes = getNativeBytes(columnIndex, true);
if (asBytes == null) {
return null;
}
if (asBytes.length == 0 /* newer versions of the server
seem to do this when they see all-zero datetime data */) {
return "0000-00-00";
}
int year = (asBytes[0] & 0xff)
| ((asBytes[1] & 0xff) << 8);
int month = asBytes[2];
int day = asBytes[3];
if (year == 0 && month == 0 && day == 0) {
return "0000-00-00";
}
}
Date dt = getNativeDate(columnIndex);
if (dt == null) {
return null;
}
return String.valueOf(dt);
case Types.TIME:
Time tm = getNativeTime(columnIndex, null, this.defaultTimeZone, false);
if (tm == null) {
return null;
}
return String.valueOf(tm);
case Types.TIMESTAMP:
if (this.connection.getNoDatetimeStringSync()) {
byte[] asBytes = getNativeBytes(columnIndex, true);
if (asBytes == null) {
return null;
}
if (asBytes.length == 0 /* newer versions of the server
seem to do this when they see all-zero datetime data */) {
return "0000-00-00 00:00:00";
}
int year = (asBytes[0] & 0xff)
| ((asBytes[1] & 0xff) << 8);
int month = asBytes[2];
int day = asBytes[3];
if (year == 0 && month == 0 && day == 0) {
return "0000-00-00 00:00:00";
}
}
Timestamp tstamp = getNativeTimestamp(columnIndex,
null, this.defaultTimeZone, false);
if (tstamp == null) {
return null;
}
String result = String.valueOf(tstamp);
if (!this.connection.getNoDatetimeStringSync()) {
return result;
}
if (result.endsWith(".0")) {
return result.substring(0, result.length() - 2);
}
default:
return extractStringFromNativeColumn(columnIndex, mysqlType);
}
}
}
/**
* 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 {
return getNativeDate(columnIndex, null);
}
/**
* 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, Calendar cal)
throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();
java.sql.Date dateToReturn = null;
if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) {
dateToReturn = this.thisRow.getNativeDate(columnIndexMinusOne,
this.connection, this, cal);
} else {
TimeZone tz = (cal != null) ? cal.getTimeZone()
: this.getDefaultTimeZone();
boolean rollForward = (tz != null && !tz.equals(this.getDefaultTimeZone()));
dateToReturn = (Date) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne,
null, Types.DATE, mysqlType, tz, rollForward, this.connection,
this);
}
//
// normally, we allow ResultSetImpl methods to check for null first,
// but with DATETIME values we have this wacky need to support
// 0000-00-00 00:00:00 -> NULL, so we have to defer
// to the RowHolder implementation, and check the return value.
//
if (dateToReturn == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return dateToReturn;
}
java.sql.Date getNativeDateViaParseConversion(int columnIndex) throws SQLException {
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getDate()", columnIndex,
this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
new int[] { MysqlDefs.FIELD_TYPE_DATE });
}
String stringVal = getNativeString(columnIndex);
return getDateFromString(stringVal, columnIndex, null);
}
/**
* 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);
columnIndex--; // / JDBC is 1-based
if (this.thisRow.isNull(columnIndex)) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
Field f= this.fields[columnIndex];
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_DOUBLE:
return this.thisRow.getNativeDouble(columnIndex);
case MysqlDefs.FIELD_TYPE_TINY:
if (!f.isUnsigned()) {
return getNativeByte(columnIndex + 1);
}
return getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
if (!f.isUnsigned()) {
return getNativeShort(columnIndex + 1);
}
return getNativeInt(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
if (!f.isUnsigned()) {
return getNativeInt(columnIndex + 1);
}
return getNativeLong(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_LONGLONG:
long valueAsLong = getNativeLong(columnIndex + 1);
if (!f.isUnsigned()) {
return valueAsLong;
}
BigInteger asBigInt = convertLongToUlong(valueAsLong);
// TODO: Check for overflow
return asBigInt.doubleValue();
case MysqlDefs.FIELD_TYPE_FLOAT:
return getNativeFloat(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_BIT:
return getNumericRepresentationOfSQLBitType(columnIndex + 1);
default:
String stringVal = getNativeString(columnIndex + 1);
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getDouble()", columnIndex,
stringVal, this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getDoubleFromString(stringVal, columnIndex + 1);
}
}
/**
* 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);
columnIndex--; // / JDBC is 1-based
if (this.thisRow.isNull(columnIndex)) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
Field f = this.fields[columnIndex];
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_BIT:
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
return valueAsLong;
case MysqlDefs.FIELD_TYPE_DOUBLE:
// Only foolproof way to check for overflow
// Not efficient, but if you don't want to be inefficient, use the
// correct binding for the type!
Double valueAsDouble = new Double(getNativeDouble(columnIndex + 1));
float valueAsFloat = valueAsDouble.floatValue();
if (this.jdbcCompliantTruncationForReads &&
valueAsFloat == Float.NEGATIVE_INFINITY ||
valueAsFloat == Float.POSITIVE_INFINITY) {
throwRangeException(valueAsDouble.toString(),
columnIndex + 1, Types.FLOAT);
}
return (float) getNativeDouble(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_TINY:
if (!f.isUnsigned()) {
return getNativeByte(columnIndex + 1);
}
return getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
if (!f.isUnsigned()) {
return getNativeShort(columnIndex + 1);
}
return getNativeInt(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
if (!f.isUnsigned()) {
return getNativeInt(columnIndex + 1);
}
return getNativeLong(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_LONGLONG:
valueAsLong = getNativeLong(columnIndex + 1);
if (!f.isUnsigned()) {
return valueAsLong;
}
BigInteger asBigInt = convertLongToUlong(valueAsLong);
// TODO: Check for overflow
return asBigInt.floatValue();
case MysqlDefs.FIELD_TYPE_FLOAT:
return this.thisRow.getNativeFloat(columnIndex);
default:
String stringVal = getNativeString(columnIndex + 1);
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getFloat()", columnIndex,
stringVal, this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getFloatFromString(stringVal, columnIndex + 1);
}
}
/**
* 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 {
return getNativeInt(columnIndex, true);
}
protected int getNativeInt(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
columnIndex--; // / JDBC is 1-based
if (this.thisRow.isNull(columnIndex)) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
Field f = this.fields[columnIndex];
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_BIT:
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
(valueAsLong < Integer.MIN_VALUE
|| valueAsLong > Integer.MAX_VALUE)) {
throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
Types.INTEGER);
}
return (short)valueAsLong;
case MysqlDefs.FIELD_TYPE_TINY:
byte tinyintVal = getNativeByte(columnIndex + 1, false);
if (!f.isUnsigned() || tinyintVal >= 0) {
return tinyintVal;
}
return tinyintVal + 256;
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
short asShort = getNativeShort(columnIndex + 1, false);
if (!f.isUnsigned() || asShort >= 0) {
return asShort;
}
return asShort + 65536;
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
int valueAsInt = this.thisRow.getNativeInt(columnIndex);
if (!f.isUnsigned()) {
return valueAsInt;
}
valueAsLong = (valueAsInt >= 0) ?
valueAsInt : valueAsInt + 4294967296L;
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
valueAsLong > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex + 1, Types.INTEGER);
}
return (int)valueAsLong;
case MysqlDefs.FIELD_TYPE_LONGLONG:
valueAsLong = getNativeLong(columnIndex + 1, false, true);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsLong < Integer.MIN_VALUE
|| valueAsLong > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex + 1, Types.INTEGER);
}
}
return (int) valueAsLong;
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.INTEGER);
}
}
return (int) valueAsDouble;
case MysqlDefs.FIELD_TYPE_FLOAT:
valueAsDouble = getNativeFloat(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Integer.MIN_VALUE
|| valueAsDouble > Integer.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.INTEGER);
}
}
return (int) valueAsDouble;
default:
String stringVal = getNativeString(columnIndex + 1);
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getInt()", columnIndex,
stringVal, this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getIntFromString(stringVal, columnIndex + 1);
}
}
/**
* 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 {
return getNativeLong(columnIndex, true, true);
}
protected long getNativeLong(int columnIndex, boolean overflowCheck,
boolean expandUnsignedLong) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
columnIndex--; // / JDBC is 1-based
if (this.thisRow.isNull(columnIndex)) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
Field f = this.fields[columnIndex];
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_BIT:
return getNumericRepresentationOfSQLBitType(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_TINY:
if (!f.isUnsigned()) {
return getNativeByte(columnIndex + 1);
}
return getNativeInt(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_SHORT:
if (!f.isUnsigned()) {
return getNativeShort(columnIndex + 1);
}
return getNativeInt(columnIndex + 1, false);
case MysqlDefs.FIELD_TYPE_YEAR:
return getNativeShort(columnIndex + 1);
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
int asInt = getNativeInt(columnIndex + 1, false);
if (!f.isUnsigned() || asInt >= 0) {
return asInt;
}
return asInt + 4294967296L;
case MysqlDefs.FIELD_TYPE_LONGLONG:
long valueAsLong = this.thisRow.getNativeLong(columnIndex);
if (!f.isUnsigned() || !expandUnsignedLong) {
return valueAsLong;
}
BigInteger asBigInt = convertLongToUlong(valueAsLong);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
((asBigInt.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0 ) ||
(asBigInt.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0))) {
throwRangeException(asBigInt.toString(),
columnIndex + 1, Types.BIGINT);
}
return getLongFromString(asBigInt.toString(), columnIndex);
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Long.MIN_VALUE
|| valueAsDouble > Long.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.BIGINT);
}
}
return (long) valueAsDouble;
case MysqlDefs.FIELD_TYPE_FLOAT:
valueAsDouble = getNativeFloat(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Long.MIN_VALUE
|| valueAsDouble > Long.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.BIGINT);
}
}
return (long) valueAsDouble;
default:
String stringVal = getNativeString(columnIndex + 1);
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getLong()", columnIndex,
stringVal, this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getLongFromString(stringVal, columnIndex + 1);
}
}
/**
* 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 SQLError.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 {
return getNativeShort(columnIndex, true);
}
protected short getNativeShort(int columnIndex, boolean overflowCheck) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
columnIndex--; // / JDBC is 1-based
if (this.thisRow.isNull(columnIndex)) {
this.wasNullFlag = true;
return 0;
}
this.wasNullFlag = false;
Field f = this.fields[columnIndex];
switch (f.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_TINY:
byte tinyintVal = getNativeByte(columnIndex + 1, false);
if (!f.isUnsigned() || tinyintVal >= 0) {
return tinyintVal;
}
return (short)(tinyintVal + (short)256);
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_YEAR:
short asShort = this.thisRow.getNativeShort(columnIndex);
if (!f.isUnsigned()) {
return asShort;
}
int valueAsInt = asShort & 0xffff;
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
valueAsInt > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsInt),
columnIndex + 1, Types.SMALLINT);
}
return (short)valueAsInt;
case MysqlDefs.FIELD_TYPE_INT24:
case MysqlDefs.FIELD_TYPE_LONG:
if (!f.isUnsigned()) {
valueAsInt = getNativeInt(columnIndex + 1, false);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
valueAsInt > Short.MAX_VALUE ||
valueAsInt < Short.MIN_VALUE) {
throwRangeException(String.valueOf(valueAsInt),
columnIndex + 1, Types.SMALLINT);
}
return (short)valueAsInt;
}
long valueAsLong = getNativeLong(columnIndex + 1, false, true);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
valueAsLong > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex + 1, Types.SMALLINT);
}
return (short)valueAsLong;
case MysqlDefs.FIELD_TYPE_LONGLONG:
valueAsLong = getNativeLong(columnIndex + 1, false, false);
if (!f.isUnsigned()) {
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsLong < Short.MIN_VALUE
|| valueAsLong > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsLong),
columnIndex + 1, Types.SMALLINT);
}
}
return (short) valueAsLong;
}
BigInteger asBigInt = convertLongToUlong(valueAsLong);
if (overflowCheck && this.jdbcCompliantTruncationForReads &&
((asBigInt.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) > 0 ) ||
(asBigInt.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) < 0))) {
throwRangeException(asBigInt.toString(),
columnIndex + 1, Types.SMALLINT);
}
return (short)getIntFromString(asBigInt.toString(), columnIndex + 1);
case MysqlDefs.FIELD_TYPE_DOUBLE:
double valueAsDouble = getNativeDouble(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Short.MIN_VALUE
|| valueAsDouble > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble),
columnIndex + 1, Types.SMALLINT);
}
}
return (short) valueAsDouble;
case MysqlDefs.FIELD_TYPE_FLOAT:
float valueAsFloat = getNativeFloat(columnIndex + 1);
if (overflowCheck && this.jdbcCompliantTruncationForReads) {
if (valueAsFloat < Short.MIN_VALUE
|| valueAsFloat > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsFloat),
columnIndex + 1, Types.SMALLINT);
}
}
return (short) valueAsFloat;
default:
String stringVal = getNativeString(columnIndex + 1);
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getShort()", columnIndex,
stringVal, this.fields[columnIndex],
new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
MysqlDefs.FIELD_TYPE_TINY,
MysqlDefs.FIELD_TYPE_SHORT,
MysqlDefs.FIELD_TYPE_LONG,
MysqlDefs.FIELD_TYPE_LONGLONG,
MysqlDefs.FIELD_TYPE_FLOAT });
}
return getShortFromString(stringVal, columnIndex + 1);
}
}
/**
* 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 (this.fields == null) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$
SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, getExceptionInterceptor());
}
if (this.thisRow.isNull(columnIndex - 1)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
String stringVal = null;
Field field = this.fields[columnIndex - 1];
// TODO: Check Types Here.
stringVal = getNativeConvertToString(columnIndex, field);
int mysqlType = field.getMysqlType();
if (mysqlType != MysqlDefs.FIELD_TYPE_TIMESTAMP &&
mysqlType != MysqlDefs.FIELD_TYPE_DATE &&
field.isZeroFill() && (stringVal != null)) {
int origLength = stringVal.length();
StringBuffer zeroFillBuf = new StringBuffer(origLength);
long numZeros = field.getLength() - origLength;
for (long i = 0; i < numZeros; i++) {
zeroFillBuf.append('0');
}
zeroFillBuf.append(stringVal);
stringVal = zeroFillBuf.toString();
}
return stringVal;
}
private Time getNativeTime(int columnIndex, Calendar targetCalendar,
TimeZone tz, boolean rollForward)
throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();
Time timeVal = null;
if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) {
timeVal = this.thisRow.getNativeTime(columnIndexMinusOne,
targetCalendar, tz, rollForward, this.connection, this);
} else {
timeVal = (Time) this.thisRow.getNativeDateTimeValue(columnIndexMinusOne,
null, Types.TIME, mysqlType, tz, rollForward, this.connection,
this);
}
//
// normally, we allow ResultSetImpl methods to check for null first,
// but with DATETIME values we have this wacky need to support
// 0000-00-00 00:00:00 -> NULL, so we have to defer
// to the RowHolder implementation, and check the return value.
//
if (timeVal == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return timeVal;
}
Time getNativeTimeViaParseConversion(int columnIndex, Calendar targetCalendar,
TimeZone tz, boolean rollForward) throws SQLException {
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getTime()", columnIndex,
this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
new int[] { MysqlDefs.FIELD_TYPE_TIME });
}
String strTime = getNativeString(columnIndex);
return getTimeFromString(strTime, targetCalendar, columnIndex, tz, rollForward);
}
private Timestamp getNativeTimestamp(int columnIndex,
Calendar targetCalendar,
TimeZone tz,
boolean rollForward) throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
Timestamp tsVal = null;
int mysqlType = this.fields[columnIndexMinusOne].getMysqlType();
switch (mysqlType) {
case MysqlDefs.FIELD_TYPE_DATETIME:
case MysqlDefs.FIELD_TYPE_TIMESTAMP:
tsVal = this.thisRow.getNativeTimestamp(columnIndexMinusOne,
targetCalendar, tz, rollForward, this.connection, this);
break;
default:
tsVal = (Timestamp) this.thisRow.getNativeDateTimeValue(
columnIndexMinusOne, null, Types.TIMESTAMP, mysqlType, tz,
rollForward, this.connection, this);
}
//
// normally, we allow ResultSetImpl methods to check for null first,
// but with DATETIME values we have this wacky need to support
// 0000-00-00 00:00:00 -> NULL, so we have to defer
// to the RowHolder implementation, and check the return value.
//
if (tsVal == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return tsVal;
}
Timestamp getNativeTimestampViaParseConversion(int columnIndex, Calendar targetCalendar,
TimeZone tz, boolean rollForward) throws SQLException {
if (this.useUsageAdvisor) {
issueConversionViaParsingWarning("getTimestamp()", columnIndex,
this.thisRow.getColumnValue(columnIndex - 1), this.fields[columnIndex - 1],
new int[] { MysqlDefs.FIELD_TYPE_TIMESTAMP,
MysqlDefs.FIELD_TYPE_DATETIME });
}
String strTimestamp = getNativeString(columnIndex);
return getTimestampFromString(columnIndex, targetCalendar, strTimestamp, tz,
rollForward);
}
// ---------------------------------------------------------------------
// Updates
// ---------------------------------------------------------------------
/**
* 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);
}
/**
* @see ResultSetInternalMethods#getURL(int)
*/
protected URL getNativeURL(int colIndex) throws SQLException {
String val = getString(colIndex);
if (val == null) {
return null;
}
try {
return new URL(val);
} catch (MalformedURLException mfe) {
throw SQLError.createSQLException(Messages
.getString("ResultSet.Malformed_URL____141")
+ val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
}
/**
* DOCUMENT ME!
*
* @return Returns the nextResultSet, if any, null if none exists.
*/
public synchronized ResultSetInternalMethods getNextResultSet() {
return this.nextResultSet;
}
/**
* 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);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
Field field;
field = this.fields[columnIndexMinusOne];
switch (field.getSQLType()) {
case Types.BIT:
case Types.BOOLEAN:
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT
&& !field.isSingleBit()) {
return getBytes(columnIndex);
}
// valueOf would be nicer here, but it isn't
// present in JDK-1.3.1, which is what the CTS
// uses.
return Boolean.valueOf(getBoolean(columnIndex));
case Types.TINYINT:
if (!field.isUnsigned()) {
return Integer.valueOf(getByte(columnIndex));
}
return Integer.valueOf(getInt(columnIndex));
case Types.SMALLINT:
return Integer.valueOf(getInt(columnIndex));
case Types.INTEGER:
if (!field.isUnsigned() ||
field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
return Integer.valueOf(getInt(columnIndex));
}
return Long.valueOf(getLong(columnIndex));
case Types.BIGINT:
if (!field.isUnsigned()) {
return Long.valueOf(getLong(columnIndex));
}
String stringVal = getString(columnIndex);
if (stringVal == null) {
return null;
}
try {
return new BigInteger(stringVal);
} catch (NumberFormatException nfe) {
throw SQLError.createSQLException(Messages.getString(
"ResultSet.Bad_format_for_BigInteger", new Object[] {
Integer.valueOf(columnIndex), stringVal }),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); //$NON-NLS-1$
}
case Types.DECIMAL:
case Types.NUMERIC:
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 SQLError.createSQLException(
Messages
.getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$
new Object[] {stringVal, Integer.valueOf(columnIndex)}),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
return val;
}
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:
if (!field.isOpaqueBinary()) {
return getString(columnIndex);
}
return getBytes(columnIndex);
case Types.LONGVARCHAR:
if (!field.isOpaqueBinary()) {
return getStringForClob(columnIndex);
}
return getBytes(columnIndex);
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_GEOMETRY) {
return getBytes(columnIndex);
} else if (field.isBinary() || field.isBlob()) {
byte[] data = getBytes(columnIndex);
if (this.connection.getAutoDeserialize()) {
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 SQLError.createSQLException(
Messages
.getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
+ cnfe.toString()
+ Messages
.getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor()); //$NON-NLS-1$
} catch (IOException ex) {
obj = data; // not serialized?
}
} else {
return getString(columnIndex);
}
}
return obj;
}
return data;
}
return getBytes(columnIndex);
case Types.DATE:
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
&& !this.connection.getYearIsDateType()) {
return Short.valueOf(getShort(columnIndex));
}
return getDate(columnIndex);
case Types.TIME:
return getTime(columnIndex);
case Types.TIMESTAMP:
return getTimestamp(columnIndex);
default:
return getString(columnIndex);
}
}
@SuppressWarnings("unchecked")
public T getObject(int columnIndex, Class type) throws SQLException {
if (type == null) {
throw SQLError.createSQLException("Type parameter can not be null",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
if (type.equals(String.class)) {
return (T) getString(columnIndex);
} else if (type.equals(BigDecimal.class)) {
return (T) getBigDecimal(columnIndex);
} else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE)) {
return (T) Boolean.valueOf(getBoolean(columnIndex));
} else if (type.equals(Integer.class) || type.equals(Integer.TYPE)) {
return (T) Integer.valueOf(getInt(columnIndex));
} else if (type.equals(Long.class) || type.equals(Long.TYPE)) {
return (T) Long.valueOf(getLong(columnIndex));
} else if (type.equals(Float.class) || type.equals(Float.TYPE)) {
return (T) Float.valueOf(getFloat(columnIndex));
} else if (type.equals(Double.class) || type.equals(Double.TYPE)) {
return (T) Double.valueOf(getDouble(columnIndex));
} else if (type.equals(byte[].class)) {
return (T) getBytes(columnIndex);
} else if (type.equals(java.sql.Date.class)) {
return (T) getDate(columnIndex);
} else if (type.equals(Time.class)) {
return (T) getTime(columnIndex);
} else if (type.equals(Timestamp.class)) {
return (T) getTimestamp(columnIndex);
} else if (type.equals(Clob.class)) {
return (T) getClob(columnIndex);
} else if (type.equals(Blob.class)) {
return (T) getBlob(columnIndex);
} else if (type.equals(Array.class)) {
return (T) getArray(columnIndex);
} else if (type.equals(Ref.class)) {
return (T) getRef(columnIndex);
} else if (type.equals(URL.class)) {
return (T) getURL(columnIndex);
// } else if (type.equals(Struct.class)) {
//
// }
// } else if (type.equals(RowId.class)) {
//
// } else if (type.equals(NClob.class)) {
//
// } else if (type.equals(SQLXML.class)) {
} else {
if (this.connection.getAutoDeserialize()) {
try {
return (T) getObject(columnIndex);
} catch (ClassCastException cce) {
SQLException sqlEx = SQLError.createSQLException("Conversion not supported for type " + type.getName(),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
sqlEx.initCause(cce);
throw sqlEx;
}
}
throw SQLError.createSQLException("Conversion not supported for type " + type.getName(),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
// JDBC-4.1
public T getObject(String columnLabel, Class type) throws SQLException {
return getObject(findColumn(columnLabel), type);
}
/**
* 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);
}
/**
* 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 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);
}
public Object getObjectStoredProc(int columnIndex, int desiredSqlType)
throws SQLException {
checkRowPos();
checkColumnBounds(columnIndex);
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
Field field;
field = this.fields[columnIndex - 1];
switch (desiredSqlType) {
case Types.BIT:
case Types.BOOLEAN:
// valueOf would be nicer here, but it isn't
// present in JDK-1.3.1, which is what the CTS
// uses.
return Boolean.valueOf(getBoolean(columnIndex));
case Types.TINYINT:
return Integer.valueOf(getInt(columnIndex));
case Types.SMALLINT:
return Integer.valueOf(getInt(columnIndex));
case Types.INTEGER:
if (!field.isUnsigned() ||
field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
return Integer.valueOf(getInt(columnIndex));
}
return Long.valueOf(getLong(columnIndex));
case Types.BIGINT:
if (field.isUnsigned()) {
return getBigDecimal(columnIndex);
}
return Long.valueOf(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 SQLError.createSQLException(
Messages
.getString("ResultSet.Bad_format_for_BigDecimal", //$NON-NLS-1$
new Object[] {stringVal, Integer.valueOf(columnIndex)}),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
return val;
}
return null;
case Types.REAL:
return new Float(getFloat(columnIndex));
case Types.FLOAT:
if (!this.connection.getRunningCTS13()) {
return new Double(getFloat(columnIndex));
}
return new Float(getFloat(columnIndex)); // NB - bug in JDBC
// compliance test,
// according
// to JDBC spec, FLOAT type should return DOUBLE
// but causes ClassCastException in CTS :(
case Types.DOUBLE:
return new Double(getDouble(columnIndex));
case Types.CHAR:
case Types.VARCHAR:
return getString(columnIndex);
case Types.LONGVARCHAR:
return getStringForClob(columnIndex);
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
return getBytes(columnIndex);
case Types.DATE:
if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
&& !this.connection.getYearIsDateType()) {
return Short.valueOf(getShort(columnIndex));
}
return getDate(columnIndex);
case Types.TIME:
return getTime(columnIndex);
case Types.TIMESTAMP:
return getTimestamp(columnIndex);
default:
return getString(columnIndex);
}
}
public Object getObjectStoredProc(int i, java.util.Map