%PDF-1.5 %���� ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY
| Server IP : kowitt.ac.th / Your IP : 216.73.216.106 Web Server : Microsoft-IIS/7.5 System : Windows NT SERVER02 6.1 build 7601 (Windows Server 2008 R2 Standard Edition Service Pack 1) i586 User : IUSR ( 0) PHP Version : 5.6.31 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : C:/Program Files (x86)/MySQL/Connector.J 5.1/src/com/mysql/jdbc/ |
Upload File : |
/*
Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
The MySQL Connector/J is licensed under the terms of the GPLv2
<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
this software, see the FOSS License Exception
<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
This program is free software; you can redistribute it and/or modify it under the terms
of the GNU General Public License as published by the Free Software Foundation; version 2
of the License.
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., 51 Franklin St, Fifth
Floor, Boston, MA 02110-1301 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.
*
* <P>
* 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.
* </p>
*
* <P>
* 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.
* </p>
*
* <P>
* For maximum portability, ResultSet columns within each row should be read in left-to-right order and each column should be read only once.
* </p>
*
* <P>
* 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.
* </p>
*
* <P>
* 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.
* </p>
*
* <P>
* 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.
* </p>
*
* <P>
* The number, types and properties of a ResultSet's columns are provided by the ResultSetMetaData object returned by the getMetaData method.
* </p>
*/
public class ResultSetImpl implements ResultSetInternalMethods {
private static final Constructor<?> JDBC_4_RS_4_ARG_CTOR;
private static final Constructor<?> JDBC_4_RS_5_ARG_CTOR;;
private static final Constructor<?> JDBC_4_UPD_RS_5_ARG_CTOR;
static {
if (Util.isJdbc4()) {
try {
String jdbc4ClassName = Util.isJdbc42() ? "com.mysql.jdbc.JDBC42ResultSet" : "com.mysql.jdbc.JDBC4ResultSet";
JDBC_4_RS_4_ARG_CTOR = Class.forName(jdbc4ClassName).getConstructor(
new Class[] { Long.TYPE, Long.TYPE, MySQLConnection.class, com.mysql.jdbc.StatementImpl.class });
JDBC_4_RS_5_ARG_CTOR = Class.forName(jdbc4ClassName).getConstructor(
new Class[] { String.class, Field[].class, RowData.class, MySQLConnection.class, com.mysql.jdbc.StatementImpl.class });
jdbc4ClassName = Util.isJdbc42() ? "com.mysql.jdbc.JDBC42UpdatableResultSet" : "com.mysql.jdbc.JDBC4UpdatableResultSet";
JDBC_4_UPD_RS_5_ARG_CTOR = Class.forName(jdbc4ClassName).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_5_ARG_CTOR = null;
JDBC_4_UPD_RS_5_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<String, Integer> 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<String, Integer> 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;
/** Are we in the middle of doing updates to the current row? */
protected boolean doingUpdates = false;
protected ProfilerEventHandler eventSink = null;
Calendar fastDefaultCal = null;
Calendar fastClientCal = 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<String, Integer> fullColumnNameToIndex = null;
protected Map<String, Integer> 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_5_ARG_CTOR, new Object[] { catalog, fields, tuples, conn, creatorStmt },
conn.getExceptionInterceptor());
}
return (ResultSetImpl) Util.handleNewInstance(JDBC_4_UPD_RS_5_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
* @param creatorStmt
*/
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();
this.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
*
* @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.exceptionInterceptor = this.connection.getExceptionInterceptor();
this.useStrictFloatingPoint = this.connection.getStrictFloatingPoint();
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 (NonRegisteringDriver.DEBUG) {
System.out.println(Messages.getString("ResultSet.Retrieved__1") + this.updateCount + " rows");
}
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
this.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<String, Integer>();
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<String> tableNamesSet = new HashSet<String>();
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 Calendar getFastDefaultCalendar() {
if (this.fastDefaultCal == null) {
this.fastDefaultCal = new GregorianCalendar(Locale.US);
this.fastDefaultCal.setTimeZone(this.getDefaultTimeZone());
}
return this.fastDefaultCal;
}
private synchronized Calendar getFastClientCalendar() {
if (this.fastClientCal == null) {
this.fastClientCal = new GregorianCalendar(Locale.US);
}
return this.fastClientCal;
}
/**
* JDBC 2.0
*
* <p>
* Move to an absolute row number in the result set.
* </p>
*
* <p>
* 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.
* </p>
*
* <p>
* 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.
* </p>
*
* <p>
* 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.
* </p>
*
* <p>
* Note: Calling absolute(1) is the same as calling first(). Calling absolute(-1) is the same as calling last().
* </p>
*
* @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
*
* <p>
* Moves to the end of the result set, just after the last row. Has no effect if the result set contains no rows.
* </p>
*
* @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
*
* <p>
* Moves to the front of the result set, just before the first row. Has no effect if the result set contains no rows.
* </p>
*
* @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, Integer>(String.CASE_INSENSITIVE_ORDER);
this.fullColumnNameToIndex = new TreeMap<String, Integer>(String.CASE_INSENSITIVE_ORDER);
this.columnNameToIndex = new TreeMap<String, Integer>(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
*/
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"),
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());
} 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());
}
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");
this.onValidRow = false;
} else if (this.rowData.isBeforeFirst()) {
this.invalidRowReason = Messages.getString("ResultSet.Before_start_of_result_set_146");
this.onValidRow = false;
} else if (this.rowData.isAfterLast()) {
this.invalidRowReason = Messages.getString("ResultSet.After_end_of_result_set_148");
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.
*
* <p>
* <B>Note:</B> 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.
* </p>
*
* @exception SQLException
* if a database access error occurs
*/
public void close() throws SQLException {
realClose(true);
}
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
*/
public void deleteRow() throws SQLException {
throw new NotUpdatable();
}
/**
* @param columnIndex
* @param stringVal
* @param mysqlType
* @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].getEncoding();
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()) {
Calendar targetCalendar = cal;
if (cal == null) {
if (this.connection.getNoTimezoneConversionForDateType()) {
targetCalendar = getFastClientCalendar();
} else {
targetCalendar = getFastDefaultCalendar();
}
}
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastDateCreate(year, month, day, targetCalendar);
}
boolean useGmtMillis = cal == null && !this.connection.getNoTimezoneConversionForDateType() && this.connection.getUseGmtMillisForDatetimes();
return TimeUtil.fastDateCreate(useGmtMillis, useGmtMillis ? getGmtCalendar() : targetCalendar, targetCalendar, 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) {
cal = getFastDefaultCalendar();
}
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) {
cal = getFastDefaultCalendar();
}
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"),
SQLError.SQL_STATE_COLUMN_NOT_FOUND, getExceptionInterceptor());
}
}
/**
* JDBC 2.0
*
* <p>
* Moves to the first row in the result set.
* </p>
*
* @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
*/
public java.sql.Array getArray(int i) throws SQLException {
checkColumnBounds(i);
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* 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
*/
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.
*
* <p>
* <B>Note:</B> 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.
* </p>
*
* @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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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());
}
}
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
*/
@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", 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());
}
}
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());
}
}
}
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));
}
/**
* @param columnName
* @param scale
*
* @throws SQLException
*
* @deprecated
*/
@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);
}
}
}
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);
}
}
} 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);
}
}
}
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);
}
}
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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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 + Messages.getString("ResultSet.___is_out_of_range_[-127,127]_174"),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* Get the value of a column in the current row as a Java byte array.
*
* <p>
* <b>Be warned</b> If the blob is huge, then you may run out of memory.
* </p>
*
* @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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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.getServerCharset(), 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
*
* <p>
* Get the value of a column in the current row as a java.io.Reader.
* </p>
*
* @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
*
* <p>
* Get the value of a column in the current row as a java.io.Reader.
* </p>
*
* @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
*
* <p>
* 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.
* </p>
*
* <p>
* 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.
* </p>
*
* <p>
* <B>Note:</B> If positioned update is not supported, a SQLException is thrown.
* </p>
*
* @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());
}
/**
* 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;
}
/**
* @param columnName
*
* @throws java.sql.SQLException
*/
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();
// truncate fractional part
int dec = stringVal.indexOf(".");
if (dec > -1) {
stringVal = stringVal.substring(0, dec);
}
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());
}
} 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());
}
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());
sqlEx.initCause(e);
throw sqlEx;
}
}
private TimeZone getDefaultTimeZone() {
return this.useLegacyDatetimeCode ? this.connection.getDefaultTimeZone() : this.serverTimeZoneTz;
}
/**
* 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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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);
}
/**
* @param columnName
*
* @throws SQLException
*/
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 + Messages.getString("ResultSet.___in_column__201")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* 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].getEncoding(), 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].getEncoding(), this.connection) + "'",
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 + "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
return getNativeInt(columnIndex);
}
/**
* @param columnName
*
* @throws SQLException
*/
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 + Messages.getString("ResultSet.___in_column__207")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* 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].getEncoding(), 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].getEncoding(), this.connection) + "'",
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 + "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
return getNativeLong(columnIndex, overflowCheck, true);
}
/**
* @param columnName
*
* @throws SQLException
*/
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 + Messages.getString("ResultSet.___in_column__212")
+ (columnIndexZeroBased + 1), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* 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(this.fields, this.connection.getUseOldAliasMetadataBehavior(), this.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
*/
protected java.sql.Array getNativeArray(int i) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* 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.
*
* <p>
* <B>Note:</B> 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.
* </p>
*
* @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.
*
* <p>
* <b>Be warned</b> If the blob is huge, then you may run out of memory.
* </p>
*
* @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
*
* <p>
* Get the value of a column in the current row as a java.io.Reader.
* </p>
*
* @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") + cnfe.toString()
+ Messages.getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor());
} 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.connection.getDefaultTimeZone(), 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.connection.getDefaultTimeZone(), 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
*/
protected java.sql.Ref getNativeRef(int i) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* 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"),
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();
StringBuilder zeroFillBuf = new StringBuilder(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());
}
}
/**
* @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
*
* <p>
* 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.
* </p>
*
* <p>
* This method may also be used to read database specific abstract data types.
* </p>
*
* @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());
}
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", 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") + cnfe.toString()
+ Messages.getString("ResultSet._while_reading_serialized_object_92"), getExceptionInterceptor());
} 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> T getObject(int columnIndex, Class<T> 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 (this.connection.getAutoDeserialize()) {
try {
return type.cast(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> T getObject(String columnLabel, Class<T> 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<String, Class<?>> map) throws SQLException {
return getObject(i);
}
/**
* Get the value of a column in the current row as a Java object
*
* <p>
* 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.
* </p>
*
* <p>
* This method may also be used to read database specific abstract data types.
* </p>
*
* @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<String, Class<?>> 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", 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<Object, Object> map, int desiredSqlType) throws SQLException {
return getObjectStoredProc(i, desiredSqlType);
}
public Object getObjectStoredProc(String columnName, int desiredSqlType) throws SQLException {
return getObjectStoredProc(findColumn(columnName), desiredSqlType);
}
public Object getObjectStoredProc(String colName, java.util.Map<Object, Object> map, int desiredSqlType) throws SQLException {
return getObjectStoredProc(findColumn(colName), map, desiredSqlType);
}
/**
* 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
*/
public java.sql.Ref getRef(int i) throws SQLException {
checkColumnBounds(i);
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* JDBC 2.0 Get a REF(<structured-type>) column.
*
* @param colName
* the column name
*
* @return an object representing data of an SQL REF type
*
* @throws SQLException
* as this method is not implemented.
* @throws NotImplemented
*/
public java.sql.Ref getRef(String colName) throws SQLException {
return getRef(findColumn(colName));
}
/**
* JDBC 2.0
*
* <p>
* Determine the current row number. The first row is number 1, the second number 2, etc.
* </p>
*
* @return the current row number, else return 0 if there is no current row
*
* @exception SQLException
* if a database-access error occurs.
*/
public int getRow() throws SQLException {
checkClosed();
int currentRowNumber = this.rowData.getCurrentRowNumber();
int row = 0;
// Non-dynamic result sets can be interrogated for this information
if (!this.rowData.isDynamic()) {
if ((currentRowNumber < 0) || this.rowData.isAfterLast() || this.rowData.isEmpty()) {
row = 0;
} else {
row = currentRowNumber + 1;
}
} else {
// dynamic (streaming) can not
row = currentRowNumber + 1;
}
return row;
}
/**
* Returns the server info (if any), or null if none.
*
* @return server info created for this ResultSet
*/
public String getServerInfo() {
try {
synchronized (checkClosed().getConnectionMutex()) {
return this.serverInfo;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
private long getNumericRepresentationOfSQLBitType(int columnIndex) throws SQLException {
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (this.fields[columnIndex - 1].isSingleBit() || ((byte[]) value).length == 1) {
return ((byte[]) value)[0];
}
byte[] asBytes = (byte[]) value;
int shift = 0;
long[] steps = new long[asBytes.length];
for (int i = asBytes.length - 1; i >= 0; i--) {
steps[i] = (long) (asBytes[i] & 0xff) << shift;
shift += 8;
}
long valueAsLong = 0;
for (int i = 0; i < asBytes.length; i++) {
valueAsLong |= steps[i];
}
return valueAsLong;
}
/**
* Get the value of a column in the current row as a Java short.
*
* @param columnIndex
* the first column is 1, the second is 2,...
*
* @return the column value; 0 if SQL NULL
*
* @exception SQLException
* if a database access error occurs
*/
public short getShort(int columnIndex) throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
if (this.useFastIntParsing) {
checkColumnBounds(columnIndex);
Object value = this.thisRow.getColumnValue(columnIndex - 1);
if (value == null) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
if (this.wasNullFlag) {
return 0;
}
byte[] shortAsBytes = (byte[]) value;
if (shortAsBytes.length == 0) {
return (short) convertToZeroWithEmptyCheck();
}
boolean needsFullParse = false;
for (int i = 0; i < shortAsBytes.length; i++) {
if (((char) shortAsBytes[i] == 'e') || ((char) shortAsBytes[i] == 'E')) {
needsFullParse = true;
break;
}
}
if (!needsFullParse) {
try {
return parseShortWithOverflowCheck(columnIndex, shortAsBytes, null);
} catch (NumberFormatException nfe) {
try {
// To do: Warn of over/underflow???
return parseShortAsDouble(columnIndex, StringUtils.toString(shortAsBytes));
} catch (NumberFormatException newNfe) {
// ignore, it's not a number
}
if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
if (this.jdbcCompliantTruncationForReads && (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE)) {
throwRangeException(String.valueOf(valueAsLong), columnIndex, Types.SMALLINT);
}
return (short) valueAsLong;
}
throw SQLError.createSQLException(
Messages.getString("ResultSet.Invalid_value_for_getShort()_-____96") + StringUtils.toString(shortAsBytes) + "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
}
String val = null;
try {
val = getString(columnIndex);
if ((val != null)) {
if (val.length() == 0) {
return (short) convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) {
return parseShortWithOverflowCheck(columnIndex, null, val);
}
// Convert floating point
return parseShortAsDouble(columnIndex, val);
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
return parseShortAsDouble(columnIndex, val);
} catch (NumberFormatException newNfe) {
// ignore, it's not a number
}
if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
if (this.jdbcCompliantTruncationForReads && (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE)) {
throwRangeException(String.valueOf(valueAsLong), columnIndex, Types.SMALLINT);
}
return (short) valueAsLong;
}
throw SQLError.createSQLException(Messages.getString("ResultSet.Invalid_value_for_getShort()_-____96") + val + "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
return getNativeShort(columnIndex);
}
/**
* @param columnName
*
* @throws SQLException
*/
public short getShort(String columnName) throws SQLException {
return getShort(findColumn(columnName));
}
private final short getShortFromString(String val, int columnIndex) throws SQLException {
try {
if ((val != null)) {
if (val.length() == 0) {
return (short) convertToZeroWithEmptyCheck();
}
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1) && (val.indexOf(".") == -1)) {
return parseShortWithOverflowCheck(columnIndex, null, val);
}
// Convert floating point
return parseShortAsDouble(columnIndex, val);
}
return 0; // for NULL
} catch (NumberFormatException nfe) {
try {
return parseShortAsDouble(columnIndex, val);
} catch (NumberFormatException newNfe) {
// ignore, it's not a number
}
throw SQLError.createSQLException(
Messages.getString("ResultSet.Invalid_value_for_getShort()_-____217") + val + Messages.getString("ResultSet.___in_column__218")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
}
/**
* JDBC 2.0 Return the Statement that produced the ResultSet.
*
* @return the Statment that produced the result set, or null if the result
* was produced some other way.
*
* @exception SQLException
* if a database-access error occurs
*/
public java.sql.Statement getStatement() throws SQLException {
try {
synchronized (checkClosed().getConnectionMutex()) {
if (this.wrapperStatement != null) {
return this.wrapperStatement;
}
return this.owningStatement;
}
} catch (SQLException sqlEx) {
if (!this.retainOwningStatement) {
throw SQLError.createSQLException(
"Operation not allowed on closed ResultSet. Statements "
+ "can be retained over result set closure by setting the connection property "
+ "\"retainStatementAfterResultSetClose\" to \"true\".", SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
}
if (this.wrapperStatement != null) {
return this.wrapperStatement;
}
return this.owningStatement;
}
}
/**
* Get the value of a column in the current row as a Java String
*
* @param columnIndex
* the first column is 1, the second is 2...
*
* @return the column value, null for SQL NULL
*
* @exception SQLException
* if a database access error occurs
*/
public String getString(int columnIndex) throws SQLException {
String stringVal = getStringInternal(columnIndex, true);
if (this.padCharsWithSpace && stringVal != null) {
Field f = this.fields[columnIndex - 1];
if (f.getMysqlType() == MysqlDefs.FIELD_TYPE_STRING) {
int fieldLength = (int) f.getLength() /* safe, bytes in a CHAR <= 1024 *// f.getMaxBytesPerCharacter(); /* safe, this will never be 0 */
int currentLength = stringVal.length();
if (currentLength < fieldLength) {
StringBuilder paddedBuf = new StringBuilder(fieldLength);
paddedBuf.append(stringVal);
int difference = fieldLength - currentLength;
paddedBuf.append(EMPTY_SPACE, 0, difference);
stringVal = paddedBuf.toString();
}
}
}
return stringVal;
}
/**
* The following routines simply convert the columnName into a columnIndex
* and then call the appropriate routine above.
*
* @param columnName
* is the SQL name of the column
*
* @return the column value
*
* @exception SQLException
* if a database access error occurs
*/
public String getString(String columnName) throws SQLException {
return getString(findColumn(columnName));
}
private String getStringForClob(int columnIndex) throws SQLException {
String asString = null;
String forcedEncoding = this.connection.getClobCharacterEncoding();
if (forcedEncoding == null) {
if (!this.isBinaryEncoded) {
asString = getString(columnIndex);
} else {
asString = getNativeString(columnIndex);
}
} else {
try {
byte[] asBytes = null;
if (!this.isBinaryEncoded) {
asBytes = getBytes(columnIndex);
} else {
asBytes = getNativeBytes(columnIndex, true);
}
if (asBytes != null) {
asString = StringUtils.toString(asBytes, forcedEncoding);
}
} catch (UnsupportedEncodingException uee) {
throw SQLError.createSQLException("Unsupported character encoding " + forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
}
return asString;
}
protected String getStringInternal(int columnIndex, boolean checkDateTypes) throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
checkColumnBounds(columnIndex);
if (this.fields == null) {
throw SQLError.createSQLException(Messages.getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"),
SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, getExceptionInterceptor());
}
// JDBC is 1-based, Java is not !?
int internalColumnIndex = columnIndex - 1;
if (this.thisRow.isNull(internalColumnIndex)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
Field metadata = this.fields[internalColumnIndex];
String stringVal = null;
if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
if (metadata.isSingleBit()) {
byte[] value = this.thisRow.getColumnValue(internalColumnIndex);
if (value.length == 0) {
return String.valueOf(convertToZeroWithEmptyCheck());
}
return String.valueOf(value[0]);
}
return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
}
String encoding = metadata.getEncoding();
stringVal = this.thisRow.getString(internalColumnIndex, encoding, this.connection);
//
// Special handling for YEAR type from mysql, some people want it as a DATE, others want to treat it as a SHORT
//
if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
if (!this.connection.getYearIsDateType()) {
return stringVal;
}
Date dt = getDateFromString(stringVal, columnIndex, null);
if (dt == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return dt.toString();
}
// Handles timezone conversion and zero-date behavior
if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) {
switch (metadata.getSQLType()) {
case Types.TIME:
Time tm = getTimeFromString(stringVal, null, columnIndex, this.getDefaultTimeZone(), false);
if (tm == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return tm.toString();
case Types.DATE:
Date dt = getDateFromString(stringVal, columnIndex, null);
if (dt == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return dt.toString();
case Types.TIMESTAMP:
Timestamp ts = getTimestampFromString(columnIndex, null, stringVal, this.getDefaultTimeZone(), false);
if (ts == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return ts.toString();
default:
break;
}
}
return stringVal;
}
return getNativeString(columnIndex);
}
/**
* Get the value of a column in the current row as a java.sql.Time object
*
* @param columnIndex
* the first column is 1, the second is 2...
*
* @return the column value; null if SQL NULL
*
* @throws java.sql.SQLException
* if a database access error occurs
*/
public Time getTime(int columnIndex) throws java.sql.SQLException {
return getTimeInternal(columnIndex, null, this.getDefaultTimeZone(), false);
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
* Use the calendar to construct an appropriate millisecond value for the
* Time, if the underlying database doesn't store timezone information.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param cal
* the calendar to use in constructing the time
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException
* if a database-access error occurs.
*/
public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {
return getTimeInternal(columnIndex, cal, cal.getTimeZone(), true);
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
*
* @param columnName
* is the SQL name of the column
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @throws java.sql.SQLException
* if a database-access error occurs.
*/
public Time getTime(String columnName) throws java.sql.SQLException {
return getTime(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
* Use the calendar to construct an appropriate millisecond value for the
* Time, if the underlying database doesn't store timezone information.
*
* @param columnName
* is the SQL name of the column
* @param cal
* the calendar to use in constructing the time
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException
* if a database-access error occurs.
*/
public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {
return getTime(findColumn(columnName), cal);
}
private Time getTimeFromString(String timeAsString, Calendar targetCalendar, int columnIndex, TimeZone tz, boolean rollForward) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
int hr = 0;
int min = 0;
int sec = 0;
try {
if (timeAsString == 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
//
timeAsString = timeAsString.trim();
// truncate fractional part
int dec = timeAsString.indexOf(".");
if (dec > -1) {
timeAsString = timeAsString.substring(0, dec);
}
if (timeAsString.equals("0") || timeAsString.equals("0000-00-00") || timeAsString.equals("0000-00-00 00:00:00")
|| timeAsString.equals("00000000000000")) {
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 '" + timeAsString + "' can not be represented as java.sql.Time",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
// We're left with the case of 'round' to a time Java _can_ represent, which is '00:00:00'
return fastTimeCreate(targetCalendar, 0, 0, 0);
}
this.wasNullFlag = false;
Field timeColField = this.fields[columnIndex - 1];
if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
// It's a timestamp
int length = timeAsString.length();
switch (length) {
case 19: { // YYYY-MM-DD hh:mm:ss
hr = Integer.parseInt(timeAsString.substring(length - 8, length - 6));
min = Integer.parseInt(timeAsString.substring(length - 5, length - 3));
sec = Integer.parseInt(timeAsString.substring(length - 2, length));
}
break;
case 14:
case 12: {
hr = Integer.parseInt(timeAsString.substring(length - 6, length - 4));
min = Integer.parseInt(timeAsString.substring(length - 4, length - 2));
sec = Integer.parseInt(timeAsString.substring(length - 2, length));
}
break;
case 10: {
hr = Integer.parseInt(timeAsString.substring(6, 8));
min = Integer.parseInt(timeAsString.substring(8, 10));
sec = 0;
}
break;
default:
throw SQLError.createSQLException(Messages.getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257")
+ columnIndex + "(" + this.fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
SQLWarning precisionLost = new SQLWarning(
Messages.getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") + columnIndex + "("
+ this.fields[columnIndex - 1] + ").");
if (this.warningChain == null) {
this.warningChain = precisionLost;
} else {
this.warningChain.setNextWarning(precisionLost);
}
} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
hr = Integer.parseInt(timeAsString.substring(11, 13));
min = Integer.parseInt(timeAsString.substring(14, 16));
sec = Integer.parseInt(timeAsString.substring(17, 19));
SQLWarning precisionLost = new SQLWarning(
Messages.getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") + columnIndex + "("
+ this.fields[columnIndex - 1] + ").");
if (this.warningChain == null) {
this.warningChain = precisionLost;
} else {
this.warningChain.setNextWarning(precisionLost);
}
} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
return fastTimeCreate(targetCalendar, 0, 0, 0); // midnight on the given
// date
} else {
// convert a String to a Time
if ((timeAsString.length() != 5) && (timeAsString.length() != 8)) {
throw SQLError.createSQLException(
Messages.getString("ResultSet.Bad_format_for_Time____267") + timeAsString + Messages.getString("ResultSet.___in_column__268")
+ columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
hr = Integer.parseInt(timeAsString.substring(0, 2));
min = Integer.parseInt(timeAsString.substring(3, 5));
sec = (timeAsString.length() == 5) ? 0 : Integer.parseInt(timeAsString.substring(6));
}
Calendar sessionCalendar = this.getCalendarInstanceForSessionOrNew();
return TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar, fastTimeCreate(sessionCalendar, hr, min, sec),
this.connection.getServerTimezoneTZ(), tz, rollForward);
} catch (RuntimeException ex) {
SQLException sqlEx = SQLError.createSQLException(ex.toString(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
sqlEx.initCause(ex);
throw sqlEx;
}
}
}
/**
* Get the value of a column in the current row as a java.sql.Time object in
* the given timezone
*
* @param columnIndex
* the first column is 1, the second is 2...
* @param tz
* the Timezone to use
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException
* if a database access error occurs
*/
private Time getTimeInternal(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws java.sql.SQLException {
checkRowPos();
if (this.isBinaryEncoded) {
return getNativeTime(columnIndex, targetCalendar, tz, rollForward);
}
if (!this.useFastDateParsing) {
String timeAsString = getStringInternal(columnIndex, false);
return getTimeFromString(timeAsString, targetCalendar, columnIndex, tz, rollForward);
}
checkColumnBounds(columnIndex);
int columnIndexMinusOne = columnIndex - 1;
if (this.thisRow.isNull(columnIndexMinusOne)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return this.thisRow.getTimeFast(columnIndexMinusOne, targetCalendar, tz, rollForward, this.connection, this);
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object
*
* @param columnIndex
* the first column is 1, the second is 2...
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException
* if a database access error occurs
*/
public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException {
return getTimestampInternal(columnIndex, null, this.getDefaultTimeZone(), false);
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object. Use the calendar to construct an appropriate millisecond value
* for the Timestamp, if the underlying database doesn't store timezone
* information.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param cal
* the calendar to use in constructing the timestamp
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException
* if a database-access error occurs.
*/
public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
return getTimestampInternal(columnIndex, cal, cal.getTimeZone(), true);
}
/**
* @param columnName
*
* @throws java.sql.SQLException
*/
public Timestamp getTimestamp(String columnName) throws java.sql.SQLException {
return getTimestamp(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object. Use the calendar to construct an appropriate millisecond value
* for the Timestamp, if the underlying database doesn't store timezone
* information.
*
* @param columnName
* is the SQL name of the column
* @param cal
* the calendar to use in constructing the timestamp
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException
* if a database-access error occurs.
*/
public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
return getTimestamp(findColumn(columnName), cal);
}
private Timestamp getTimestampFromString(int columnIndex, Calendar targetCalendar, String timestampValue, TimeZone tz, boolean rollForward)
throws java.sql.SQLException {
try {
this.wasNullFlag = false;
if (timestampValue == 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
//
timestampValue = timestampValue.trim();
int length = timestampValue.length();
Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ? this.connection.getUtcCalendar()
: getCalendarInstanceForSessionOrNew();
if ((length > 0)
&& (timestampValue.charAt(0) == '0')
&& (timestampValue.equals("0000-00-00") || timestampValue.equals("0000-00-00 00:00:00") || timestampValue.equals("00000000000000") || timestampValue
.equals("0"))) {
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 '" + timestampValue + "' can not be represented as java.sql.Timestamp",
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 fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
} else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastTimestampCreate(tz, Integer.parseInt(timestampValue.substring(0, 4)), 1, 1, 0, 0, 0, 0);
}
return TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar,
fastTimestampCreate(sessionCalendar, Integer.parseInt(timestampValue.substring(0, 4)), 1, 1, 0, 0, 0, 0),
this.connection.getServerTimezoneTZ(), tz, rollForward);
} else {
// Convert from TIMESTAMP or DATE
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minutes = 0;
int seconds = 0;
int nanos = 0;
// check for the fractional part
int decimalIndex = timestampValue.indexOf(".");
if (decimalIndex == length - 1) {
// if the dot is in last position
length--;
} else if (decimalIndex != -1) {
if ((decimalIndex + 2) <= length) {
nanos = Integer.parseInt(timestampValue.substring(decimalIndex + 1));
int numDigits = length - (decimalIndex + 1);
if (numDigits < 9) {
int factor = (int) (Math.pow(10, 9 - numDigits));
nanos = nanos * factor;
}
length = decimalIndex;
} else {
throw new IllegalArgumentException(); // re-thrown further down with a much better error message
}
}
switch (length) {
case 26:
case 25:
case 24:
case 23:
case 22:
case 21:
case 20:
case 19: {
year = Integer.parseInt(timestampValue.substring(0, 4));
month = Integer.parseInt(timestampValue.substring(5, 7));
day = Integer.parseInt(timestampValue.substring(8, 10));
hour = Integer.parseInt(timestampValue.substring(11, 13));
minutes = Integer.parseInt(timestampValue.substring(14, 16));
seconds = Integer.parseInt(timestampValue.substring(17, 19));
break;
}
case 14: {
year = Integer.parseInt(timestampValue.substring(0, 4));
month = Integer.parseInt(timestampValue.substring(4, 6));
day = Integer.parseInt(timestampValue.substring(6, 8));
hour = Integer.parseInt(timestampValue.substring(8, 10));
minutes = Integer.parseInt(timestampValue.substring(10, 12));
seconds = Integer.parseInt(timestampValue.substring(12, 14));
break;
}
case 12: {
year = Integer.parseInt(timestampValue.substring(0, 2));
if (year <= 69) {
year = (year + 100);
}
year += 1900;
month = Integer.parseInt(timestampValue.substring(2, 4));
day = Integer.parseInt(timestampValue.substring(4, 6));
hour = Integer.parseInt(timestampValue.substring(6, 8));
minutes = Integer.parseInt(timestampValue.substring(8, 10));
seconds = Integer.parseInt(timestampValue.substring(10, 12));
break;
}
case 10: {
if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) || (timestampValue.indexOf("-") != -1)) {
year = Integer.parseInt(timestampValue.substring(0, 4));
month = Integer.parseInt(timestampValue.substring(5, 7));
day = Integer.parseInt(timestampValue.substring(8, 10));
hour = 0;
minutes = 0;
} else {
year = Integer.parseInt(timestampValue.substring(0, 2));
if (year <= 69) {
year = (year + 100);
}
month = Integer.parseInt(timestampValue.substring(2, 4));
day = Integer.parseInt(timestampValue.substring(4, 6));
hour = Integer.parseInt(timestampValue.substring(6, 8));
minutes = Integer.parseInt(timestampValue.substring(8, 10));
year += 1900; // two-digit year
}
break;
}
case 8: {
if (timestampValue.indexOf(":") != -1) {
hour = Integer.parseInt(timestampValue.substring(0, 2));
minutes = Integer.parseInt(timestampValue.substring(3, 5));
seconds = Integer.parseInt(timestampValue.substring(6, 8));
year = 1970;
month = 1;
day = 1;
break;
}
year = Integer.parseInt(timestampValue.substring(0, 4));
month = Integer.parseInt(timestampValue.substring(4, 6));
day = Integer.parseInt(timestampValue.substring(6, 8));
year -= 1900;
month--;
break;
}
case 6: {
year = Integer.parseInt(timestampValue.substring(0, 2));
if (year <= 69) {
year = (year + 100);
}
year += 1900;
month = Integer.parseInt(timestampValue.substring(2, 4));
day = Integer.parseInt(timestampValue.substring(4, 6));
break;
}
case 4: {
year = Integer.parseInt(timestampValue.substring(0, 2));
if (year <= 69) {
year = (year + 100);
}
year += 1900;
month = Integer.parseInt(timestampValue.substring(2, 4));
day = 1;
break;
}
case 2: {
year = Integer.parseInt(timestampValue.substring(0, 2));
if (year <= 69) {
year = (year + 100);
}
year += 1900;
month = 1;
day = 1;
break;
}
default:
throw new java.sql.SQLException("Bad format for Timestamp '" + timestampValue + "' in column " + columnIndex + ".",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
if (!this.useLegacyDatetimeCode) {
return TimeUtil.fastTimestampCreate(tz, year, month, day, hour, minutes, seconds, nanos);
}
return TimeUtil.changeTimezone(this.connection, sessionCalendar, targetCalendar,
fastTimestampCreate(sessionCalendar, year, month, day, hour, minutes, seconds, nanos), this.connection.getServerTimezoneTZ(), tz,
rollForward);
}
} catch (RuntimeException e) {
SQLException sqlEx = SQLError.createSQLException("Cannot convert value '" + timestampValue + "' from column " + columnIndex + " to TIMESTAMP.",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
sqlEx.initCause(e);
throw sqlEx;
}
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object in the given timezone
*
* @param columnIndex
* the first column is 1, the second is 2...
* @param tz
* the timezone to use
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException
* if a database access error occurs
*/
private Timestamp getTimestampInternal(int columnIndex, Calendar targetCalendar, TimeZone tz, boolean rollForward) throws java.sql.SQLException {
if (this.isBinaryEncoded) {
return getNativeTimestamp(columnIndex, targetCalendar, tz, rollForward);
}
Timestamp tsVal = null;
if (!this.useFastDateParsing) {
String timestampValue = getStringInternal(columnIndex, false);
tsVal = getTimestampFromString(columnIndex, targetCalendar, timestampValue, tz, rollForward);
} else {
checkClosed();
checkRowPos();
checkColumnBounds(columnIndex);
tsVal = this.thisRow.getTimestampFast(columnIndex - 1, targetCalendar, tz, rollForward, this.connection, this);
}
if (tsVal == null) {
this.wasNullFlag = true;
} else {
this.wasNullFlag = false;
}
return tsVal;
}
/**
* JDBC 2.0 Return the type of this result set. The type is determined based
* on the statement that created the result set.
*
* @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
* TYPE_SCROLL_SENSITIVE
*
* @exception SQLException
* if a database-access error occurs
*/
public int getType() throws SQLException {
return this.resultSetType;
}
/**
* A column value can also be retrieved as a stream of Unicode characters.
* We implement this as a binary stream.
*
* @param columnIndex
* the first column is 1, the second is 2...
*
* @return a Java InputStream that delivers the database column value as a
* stream of two byte Unicode characters. If the value is SQL NULL,
* then the result is null
*
* @exception SQLException
* if a database access error occurs
*
* @see getAsciiStream
* @see getBinaryStream
* @deprecated
*/
@Deprecated
public InputStream getUnicodeStream(int columnIndex) throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
return getBinaryStream(columnIndex);
}
return getNativeBinaryStream(columnIndex);
}
/**
* @param columnName
*
* @throws SQLException
*
* @deprecated
*/
@Deprecated
public InputStream getUnicodeStream(String columnName) throws SQLException {
return getUnicodeStream(findColumn(columnName));
}
public long getUpdateCount() {
return this.updateCount;
}
public long getUpdateID() {
return this.updateId;
}
/**
* @see ResultSetInternalMethods#getURL(int)
*/
public URL getURL(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____104") + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
}
/**
* @see ResultSetInternalMethods#getURL(String)
*/
public URL getURL(String colName) throws SQLException {
String val = getString(colName);
if (val == null) {
return null;
}
try {
return new URL(val);
} catch (MalformedURLException mfe) {
throw SQLError.createSQLException(Messages.getString("ResultSet.Malformed_URL____107") + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
}
/**
* The first warning reported by calls on this ResultSet is returned.
* Subsequent ResultSet warnings will be chained to this
* java.sql.SQLWarning.
*
* <p>
* The warning chain is automatically cleared each time a new row is read.
* </p>
*
* <p>
* <B>Note:</B> This warning chain only covers warnings caused by ResultSet methods. Any warnings caused by statement methods (such as reading OUT
* parameters) will be chained on the Statement object.
* </p>
*
* @return the first java.sql.SQLWarning or null;
*
* @exception SQLException
* if a database access error occurs.
*/
public java.sql.SQLWarning getWarnings() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.warningChain;
}
}
/**
* JDBC 2.0 Insert the contents of the insert row into the result set and
* the database. Must be on the insert row when this method is called.
*
* @exception SQLException
* if a database-access error occurs, if called when not on
* the insert row, or if all non-nullable columns in the
* insert row have not been given a value
* @throws NotUpdatable
*/
public void insertRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0
*
* <p>
* Determine if the cursor is after the last row in the result set.
* </p>
*
* @return true if after the last row, false otherwise. Returns false when
* the result set contains no rows.
*
* @exception SQLException
* if a database-access error occurs.
*/
public boolean isAfterLast() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
boolean b = this.rowData.isAfterLast();
return b;
}
}
/**
* JDBC 2.0
*
* <p>
* Determine if the cursor is before the first row in the result set.
* </p>
*
* @return true if before the first row, false otherwise. Returns false when
* the result set contains no rows.
*
* @exception SQLException
* if a database-access error occurs.
*/
public boolean isBeforeFirst() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.rowData.isBeforeFirst();
}
}
/**
* JDBC 2.0
*
* <p>
* Determine if the cursor is on the first row of the result set.
* </p>
*
* @return true if on the first row, false otherwise.
*
* @exception SQLException
* if a database-access error occurs.
*/
public boolean isFirst() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.rowData.isFirst();
}
}
/**
* JDBC 2.0
*
* <p>
* Determine if the cursor is on the last row of the result set. Note: Calling isLast() may be expensive since the JDBC driver might need to fetch ahead one
* row in order to determine whether the current row is the last row in the result set.
* </p>
*
* @return true if on the last row, false otherwise.
*
* @exception SQLException
* if a database-access error occurs.
*/
public boolean isLast() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.rowData.isLast();
}
}
/**
* @param string
* @param mysqlType
* @param s
*/
private void issueConversionViaParsingWarning(String methodName, int columnIndex, Object value, Field fieldInfo, int[] typesWithNoParseConversion)
throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
StringBuilder originalQueryBuf = new StringBuilder();
if (this.owningStatement != null && this.owningStatement instanceof com.mysql.jdbc.PreparedStatement) {
originalQueryBuf.append(Messages.getString("ResultSet.CostlyConversionCreatedFromQuery"));
originalQueryBuf.append(((com.mysql.jdbc.PreparedStatement) this.owningStatement).originalSql);
originalQueryBuf.append("\n\n");
} else {
originalQueryBuf.append(".");
}
StringBuilder convertibleTypesBuf = new StringBuilder();
for (int i = 0; i < typesWithNoParseConversion.length; i++) {
convertibleTypesBuf.append(MysqlDefs.typeToName(typesWithNoParseConversion[i]));
convertibleTypesBuf.append("\n");
}
String message = Messages.getString(
"ResultSet.CostlyConversion",
new Object[] {
methodName,
Integer.valueOf(columnIndex + 1),
fieldInfo.getOriginalName(),
fieldInfo.getOriginalTableName(),
originalQueryBuf.toString(),
value != null ? value.getClass().getName() : ResultSetMetaData.getClassNameForJavaType(fieldInfo.getSQLType(),
fieldInfo.isUnsigned(), fieldInfo.getMysqlType(), fieldInfo.isBinary() || fieldInfo.isBlob(), fieldInfo.isOpaqueBinary(),
this.connection.getYearIsDateType()), MysqlDefs.typeToName(fieldInfo.getMysqlType()), convertibleTypesBuf.toString() });
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? "N/A"
: this.owningStatement.currentCatalog, this.connectionId, (this.owningStatement == null) ? (-1) : this.owningStatement.getId(),
this.resultId, System.currentTimeMillis(), 0, Constants.MILLIS_I18N, null, this.pointOfOrigin, message));
}
}
/**
* JDBC 2.0
*
* <p>
* Moves to the last row in the result set.
* </p>
*
* @return true if on a valid row, false if no rows in the result set.
*
* @exception SQLException
* if a database-access error occurs, or result set type is
* TYPE_FORWARD_ONLY.
*/
public boolean last() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
boolean b = true;
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();
}
this.rowData.beforeLast();
this.thisRow = this.rowData.next();
}
setRowPositionValidity();
return b;
}
}
// /////////////////////////////////////////
//
// These number conversion routines save
// a ton of "new()s", especially for the heavily
// used getInt() and getDouble() methods
//
// /////////////////////////////////////////
/**
* JDBC 2.0 Move the cursor to the remembered cursor position, usually the
* current row. Has no effect unless the cursor is on the insert row.
*
* @exception SQLException
* if a database-access error occurs, or the result set is
* not updatable
* @throws NotUpdatable
*/
public void moveToCurrentRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Move to the insert row. The current cursor position is
* remembered while the cursor is positioned on the insert row. The insert
* row is a special row associated with an updatable result set. It is
* essentially a buffer where a new row may be constructed by calling the
* updateXXX() methods prior to inserting the row into the result set. Only
* the updateXXX(), getXXX(), and insertRow() methods may be called when the
* cursor is on the insert row. All of the columns in a result set must be
* given a value each time this method is called before calling insertRow().
* UpdateXXX()must be called before getXXX() on a column.
*
* @exception SQLException
* if a database-access error occurs, or the result set is
* not updatable
* @throws NotUpdatable
*/
public void moveToInsertRow() throws SQLException {
throw new NotUpdatable();
}
/**
* A ResultSet is initially positioned before its first row, the first call
* to next makes the first row the current row; the second call makes the
* second row the current row, etc.
*
* <p>
* If an input stream from the previous row is open, it is implicitly closed. The ResultSet's warning chain is cleared when a new row is read
* </p>
*
* @return true if the new current is valid; false if there are no more rows
*
* @exception SQLException
* if a database access error occurs
*/
public boolean next() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
boolean b;
if (!reallyResult()) {
throw SQLError.createSQLException(Messages.getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"), SQLError.SQL_STATE_GENERAL_ERROR,
getExceptionInterceptor());
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
if (this.rowData.size() == 0) {
b = false;
} else {
this.thisRow = this.rowData.next();
if (this.thisRow == null) {
b = false;
} else {
clearWarnings();
b = true;
}
}
setRowPositionValidity();
return b;
}
}
private int parseIntAsDouble(int columnIndex, String val) throws NumberFormatException, SQLException {
if (val == null) {
return 0;
}
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;
}
private int getIntWithOverflowCheck(int columnIndex) throws SQLException {
int intValue = this.thisRow.getInt(columnIndex);
checkForIntegerTruncation(columnIndex, null, intValue);
return intValue;
}
private void checkForIntegerTruncation(int columnIndex, byte[] valueAsBytes, int intValue) throws SQLException {
if (this.jdbcCompliantTruncationForReads) {
if (intValue == Integer.MIN_VALUE || intValue == Integer.MAX_VALUE) {
String valueAsString = null;
if (valueAsBytes == null) {
valueAsString = this.thisRow.getString(columnIndex, this.fields[columnIndex].getEncoding(), this.connection);
}
long valueAsLong = Long.parseLong(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString);
if (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE) {
throwRangeException(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString, columnIndex + 1, Types.INTEGER);
}
}
}
}
private long parseLongAsDouble(int columnIndexZeroBased, String val) throws NumberFormatException, SQLException {
if (val == null) {
return 0;
}
double valueAsDouble = Double.parseDouble(val);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Long.MIN_VALUE || valueAsDouble > Long.MAX_VALUE) {
throwRangeException(val, columnIndexZeroBased + 1, Types.BIGINT);
}
}
return (long) valueAsDouble;
}
private long getLongWithOverflowCheck(int columnIndexZeroBased, boolean doOverflowCheck) throws SQLException {
long longValue = this.thisRow.getLong(columnIndexZeroBased);
if (doOverflowCheck) {
checkForLongTruncation(columnIndexZeroBased, null, longValue);
}
return longValue;
}
private long parseLongWithOverflowCheck(int columnIndexZeroBased, byte[] valueAsBytes, String valueAsString, boolean doCheck) throws NumberFormatException,
SQLException {
long longValue = 0;
if (valueAsBytes == null && valueAsString == null) {
return 0;
}
if (valueAsBytes != null) {
longValue = StringUtils.getLong(valueAsBytes);
} else {
//
// 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
//
valueAsString = valueAsString.trim();
longValue = Long.parseLong(valueAsString);
}
if (doCheck && this.jdbcCompliantTruncationForReads) {
checkForLongTruncation(columnIndexZeroBased, valueAsBytes, longValue);
}
return longValue;
}
private void checkForLongTruncation(int columnIndexZeroBased, byte[] valueAsBytes, long longValue) throws SQLException {
if (longValue == Long.MIN_VALUE || longValue == Long.MAX_VALUE) {
String valueAsString = null;
if (valueAsBytes == null) {
valueAsString = this.thisRow.getString(columnIndexZeroBased, this.fields[columnIndexZeroBased].getEncoding(), this.connection);
}
double valueAsDouble = Double.parseDouble(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString);
if (valueAsDouble < Long.MIN_VALUE || valueAsDouble > Long.MAX_VALUE) {
throwRangeException(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString, columnIndexZeroBased + 1, Types.BIGINT);
}
}
}
private short parseShortAsDouble(int columnIndex, String val) throws NumberFormatException, SQLException {
if (val == null) {
return 0;
}
double valueAsDouble = Double.parseDouble(val);
if (this.jdbcCompliantTruncationForReads) {
if (valueAsDouble < Short.MIN_VALUE || valueAsDouble > Short.MAX_VALUE) {
throwRangeException(String.valueOf(valueAsDouble), columnIndex, Types.SMALLINT);
}
}
return (short) valueAsDouble;
}
private short parseShortWithOverflowCheck(int columnIndex, byte[] valueAsBytes, String valueAsString) throws NumberFormatException, SQLException {
short shortValue = 0;
if (valueAsBytes == null && valueAsString == null) {
return 0;
}
if (valueAsBytes != null) {
shortValue = StringUtils.getShort(valueAsBytes);
} else {
//
// 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
//
valueAsString = valueAsString.trim();
shortValue = Short.parseShort(valueAsString);
}
if (this.jdbcCompliantTruncationForReads) {
if (shortValue == Short.MIN_VALUE || shortValue == Short.MAX_VALUE) {
long valueAsLong = Long.parseLong(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString);
if (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE) {
throwRangeException(valueAsString == null ? StringUtils.toString(valueAsBytes) : valueAsString, columnIndex, Types.SMALLINT);
}
}
}
return shortValue;
}
// --------------------------JDBC 2.0-----------------------------------
// ---------------------------------------------------------------------
// Getter's and Setter's
// ---------------------------------------------------------------------
/**
* The prev method is not part of JDBC, but because of the architecture of
* this driver it is possible to move both forward and backward within the
* result set.
*
* <p>
* If an input stream from the previous row is open, it is implicitly closed. The ResultSet's warning chain is cleared when a new row is read
* </p>
*
* @return true if the new current is valid; false if there are no more rows
*
* @exception java.sql.SQLException
* if a database access error occurs
*/
public boolean prev() throws java.sql.SQLException {
synchronized (checkClosed().getConnectionMutex()) {
int rowIndex = this.rowData.getCurrentRowNumber();
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
boolean b = true;
if ((rowIndex - 1) >= 0) {
rowIndex--;
this.rowData.setCurrentRow(rowIndex);
this.thisRow = this.rowData.getAt(rowIndex);
b = true;
} else if ((rowIndex - 1) == -1) {
rowIndex--;
this.rowData.setCurrentRow(rowIndex);
this.thisRow = null;
b = false;
} else {
b = false;
}
setRowPositionValidity();
return b;
}
}
/**
* JDBC 2.0
*
* <p>
* Moves to the previous row in the result set.
* </p>
*
* <p>
* Note: previous() is not the same as relative(-1) since it makes sense to call previous() when there is no current row.
* </p>
*
* @return true if on a valid row, false if off the result set.
*
* @exception SQLException
* if a database-access error occurs, or result set type is
* TYPE_FORWAR_DONLY.
*/
public boolean previous() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
return prev();
}
}
/**
* Closes this ResultSet and releases resources.
*
* @param calledExplicitly
* was realClose called by the standard ResultSet.close() method, or was it closed internally by the
* driver?
*
* @throws SQLException
* if an error occurs
*/
public void realClose(boolean calledExplicitly) throws SQLException {
MySQLConnection locallyScopedConn = this.connection;
if (locallyScopedConn == null) {
return; // already closed
}
synchronized (locallyScopedConn.getConnectionMutex()) {
// additional check in case ResultSet was closed
// while current thread was waiting for lock
if (this.isClosed) {
return;
}
try {
if (this.useUsageAdvisor) {
// Report on result set closed by driver instead of application
if (!calledExplicitly) {
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? "N/A"
: this.owningStatement.currentCatalog, this.connectionId, (this.owningStatement == null) ? (-1) : this.owningStatement.getId(),
this.resultId, System.currentTimeMillis(), 0, Constants.MILLIS_I18N, null, this.pointOfOrigin, Messages
.getString("ResultSet.ResultSet_implicitly_closed_by_driver")));
}
if (this.rowData instanceof RowDataStatic) {
// Report on possibly too-large result sets
if (this.rowData.size() > this.connection.getResultSetSizeThreshold()) {
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? Messages
.getString("ResultSet.N/A_159") : this.owningStatement.currentCatalog, this.connectionId,
(this.owningStatement == null) ? (-1) : this.owningStatement.getId(), this.resultId, System.currentTimeMillis(), 0,
Constants.MILLIS_I18N, null, this.pointOfOrigin, Messages.getString("ResultSet.Too_Large_Result_Set", new Object[] {
Integer.valueOf(this.rowData.size()), Integer.valueOf(this.connection.getResultSetSizeThreshold()) })));
}
if (!isLast() && !isAfterLast() && (this.rowData.size() != 0)) {
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? Messages
.getString("ResultSet.N/A_159") : this.owningStatement.currentCatalog, this.connectionId,
(this.owningStatement == null) ? (-1) : this.owningStatement.getId(), this.resultId, System.currentTimeMillis(), 0,
Constants.MILLIS_I18N, null, this.pointOfOrigin, Messages.getString(
"ResultSet.Possible_incomplete_traversal_of_result_set",
new Object[] { Integer.valueOf(getRow()), Integer.valueOf(this.rowData.size()) })));
}
}
//
// Report on any columns that were selected but not referenced
//
if (this.columnUsed.length > 0 && !this.rowData.wasEmpty()) {
StringBuilder buf = new StringBuilder(Messages.getString("ResultSet.The_following_columns_were_never_referenced"));
boolean issueWarn = false;
for (int i = 0; i < this.columnUsed.length; i++) {
if (!this.columnUsed[i]) {
if (!issueWarn) {
issueWarn = true;
} else {
buf.append(", ");
}
buf.append(this.fields[i].getFullName());
}
}
if (issueWarn) {
this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN, "", (this.owningStatement == null) ? "N/A"
: this.owningStatement.currentCatalog, this.connectionId, (this.owningStatement == null) ? (-1) : this.owningStatement
.getId(), 0, System.currentTimeMillis(), 0, Constants.MILLIS_I18N, null, this.pointOfOrigin, buf.toString()));
}
}
}
} finally {
if (this.owningStatement != null && calledExplicitly) {
this.owningStatement.removeOpenResultSet(this);
}
SQLException exceptionDuringClose = null;
if (this.rowData != null) {
try {
this.rowData.close();
} catch (SQLException sqlEx) {
exceptionDuringClose = sqlEx;
}
}
if (this.statementUsedForFetchingRows != null) {
try {
this.statementUsedForFetchingRows.realClose(true, false);
} catch (SQLException sqlEx) {
if (exceptionDuringClose != null) {
exceptionDuringClose.setNextException(sqlEx);
} else {
exceptionDuringClose = sqlEx;
}
}
}
this.rowData = null;
this.fields = null;
this.columnLabelToIndex = null;
this.fullColumnNameToIndex = null;
this.columnToIndexCache = null;
this.eventSink = null;
this.warningChain = null;
if (!this.retainOwningStatement) {
this.owningStatement = null;
}
this.catalog = null;
this.serverInfo = null;
this.thisRow = null;
this.fastDefaultCal = null;
this.fastClientCal = null;
this.connection = null;
this.isClosed = true;
if (exceptionDuringClose != null) {
throw exceptionDuringClose;
}
}
}
}
/**
* Returns true if this ResultSet is closed.
*/
public boolean isClosed() throws SQLException {
return this.isClosed;
}
public boolean reallyResult() {
if (this.rowData != null) {
return true;
}
return this.reallyResult;
}
/**
* JDBC 2.0 Refresh the value of the current row with its current value in
* the database. Cannot be called when on the insert row. The refreshRow()
* method provides a way for an application to explicitly tell the JDBC
* driver to refetch a row(s) from the database. An application may want to
* call refreshRow() when caching or prefetching is being done by the JDBC
* driver to fetch the latest value of a row from the database. The JDBC
* driver may actually refresh multiple rows at once if the fetch size is
* greater than one. All values are refetched subject to the transaction
* isolation level and cursor sensitivity. If refreshRow() is called after
* calling updateXXX(), but before calling updateRow() then the updates made
* to the row are lost. Calling refreshRow() frequently will likely slow
* performance.
*
* @exception SQLException
* if a database-access error occurs, or if called when on
* the insert row.
* @throws NotUpdatable
*/
public void refreshRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0
*
* <p>
* Moves a relative number of rows, either positive or negative. Attempting to move beyond the first/last row in the result set positions the cursor
* before/after the the first/last row. Calling relative(0) is valid, but does not change the cursor position.
* </p>
*
* <p>
* Note: Calling relative(1) is different than calling next() since is makes sense to call next() when there is no current row, for example, when the cursor
* is positioned before the first row or after the last row of the result set.
* </p>
*
* @param rows
* the number of relative rows to move the cursor.
*
* @return true if on a row, false otherwise.
*
* @throws SQLException
* if a database-access error occurs, or there is no current
* row, or result set type is TYPE_FORWARD_ONLY.
*/
public boolean relative(int rows) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (this.rowData.size() == 0) {
setRowPositionValidity();
return false;
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
this.rowData.moveRowRelative(rows);
this.thisRow = this.rowData.getAt(this.rowData.getCurrentRowNumber());
setRowPositionValidity();
return (!this.rowData.isAfterLast() && !this.rowData.isBeforeFirst());
}
}
/**
* JDBC 2.0 Determine if this row has been deleted. A deleted row may leave
* a visible "hole" in a result set. This method can be used to detect holes
* in a result set. The value returned depends on whether or not the result
* set can detect deletions.
*
* @return true if deleted and deletes are detected
*
* @exception SQLException
* if a database-access error occurs
* @throws NotImplemented
*
* @see DatabaseMetaData#deletesAreDetected
*/
public boolean rowDeleted() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* JDBC 2.0 Determine if the current row has been inserted. The value
* returned depends on whether or not the result set can detect visible
* inserts.
*
* @return true if inserted and inserts are detected
*
* @exception SQLException
* if a database-access error occurs
* @throws NotImplemented
*
* @see DatabaseMetaData#insertsAreDetected
*/
public boolean rowInserted() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* JDBC 2.0 Determine if the current row has been updated. The value
* returned depends on whether or not the result set can detect updates.
*
* @return true if the row has been visibly updated by the owner or another,
* and updates are detected
*
* @exception SQLException
* if a database-access error occurs
* @throws NotImplemented
*
* @see DatabaseMetaData#updatesAreDetected
*/
public boolean rowUpdated() throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* Flag that this result set is 'binary' encoded (from a PreparedStatement),
* not stored as strings.
*/
protected void setBinaryEncoded() {
this.isBinaryEncoded = true;
}
/**
* JDBC 2.0 Give a hint as to the direction in which the rows in this result
* set will be processed. The initial value is determined by the statement
* that produced the result set. The fetch direction may be changed at any
* time.
*
* @param direction
* the direction to fetch rows in.
*
* @exception SQLException
* if a database-access error occurs, or the result set type
* is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
* MM.MySQL actually ignores this, because it has the whole
* result set anyway, so the direction is immaterial.
*/
public void setFetchDirection(int direction) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE) && (direction != FETCH_UNKNOWN)) {
throw SQLError.createSQLException(Messages.getString("ResultSet.Illegal_value_for_fetch_direction_64"), SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
getExceptionInterceptor());
}
this.fetchDirection = direction;
}
}
/**
* JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
* be fetched from the database when more rows are needed for this result
* set. If the fetch size specified is zero, then the JDBC driver ignores
* the value, and is free to make its own best guess as to what the fetch
* size should be. The default value is set by the statement that creates
* the result set. The fetch size may be changed at any time.
*
* @param rows
* the number of rows to fetch
*
* @exception SQLException
* if a database-access error occurs, or the condition 0 lteq
* rows lteq this.getMaxRows() is not satisfied. Currently
* ignored by this driver.
*/
public void setFetchSize(int rows) throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
if (rows < 0) { /* || rows > getMaxRows() */
throw SQLError.createSQLException(Messages.getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"),
SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor());
}
this.fetchSize = rows;
}
}
/**
* Sets the first character of the query that this result set was created
* from.
*
* @param c
* the first character of the query...uppercased
*/
public void setFirstCharOfQuery(char c) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.firstCharOfQuery = c;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
/**
* @param nextResultSet
* Sets the next result set in the result set chain for multiple
* result sets.
*/
protected synchronized void setNextResultSet(ResultSetInternalMethods nextResultSet) {
this.nextResultSet = nextResultSet;
}
public void setOwningStatement(com.mysql.jdbc.StatementImpl owningStatement) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.owningStatement = owningStatement;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
/**
* Sets the concurrency (JDBC2)
*
* @param concurrencyFlag
* CONCUR_UPDATABLE or CONCUR_READONLY
*/
protected synchronized void setResultSetConcurrency(int concurrencyFlag) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.resultSetConcurrency = concurrencyFlag;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
/**
* Sets the result set type for (JDBC2)
*
* @param typeFlag
* SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
* SCROLL_INSENSITIVE)
*/
protected synchronized void setResultSetType(int typeFlag) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.resultSetType = typeFlag;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
/**
* Sets server info (if any)
*
* @param info
* the server info message
*/
protected synchronized void setServerInfo(String info) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.serverInfo = info;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
public synchronized void setStatementUsedForFetchingRows(PreparedStatement stmt) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.statementUsedForFetchingRows = stmt;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
/**
* @param wrapperStatement
* The wrapperStatement to set.
*/
public synchronized void setWrapperStatement(java.sql.Statement wrapperStatement) {
try {
synchronized (checkClosed().getConnectionMutex()) {
this.wrapperStatement = wrapperStatement;
}
} catch (SQLException e) {
throw new RuntimeException(e); // FIXME: Need to evolve public interface
}
}
private void throwRangeException(String valueAsString, int columnIndex, int jdbcType) throws SQLException {
String datatype = null;
switch (jdbcType) {
case Types.TINYINT:
datatype = "TINYINT";
break;
case Types.SMALLINT:
datatype = "SMALLINT";
break;
case Types.INTEGER:
datatype = "INTEGER";
break;
case Types.BIGINT:
datatype = "BIGINT";
break;
case Types.REAL:
datatype = "REAL";
break;
case Types.FLOAT:
datatype = "FLOAT";
break;
case Types.DOUBLE:
datatype = "DOUBLE";
break;
case Types.DECIMAL:
datatype = "DECIMAL";
break;
default:
datatype = " (JDBC type '" + jdbcType + "')";
}
throw SQLError.createSQLException("'" + valueAsString + "' in column '" + columnIndex + "' is outside valid range for the datatype " + datatype + ".",
SQLError.SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE, getExceptionInterceptor());
}
@Override
public String toString() {
if (this.reallyResult) {
return super.toString();
}
return "Result set representing update count of " + this.updateCount;
}
/**
* @see ResultSetInternalMethods#updateArray(int, Array)
*/
public void updateArray(int arg0, Array arg1) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* @see ResultSetInternalMethods#updateArray(String, Array)
*/
public void updateArray(String arg0, Array arg1) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
* @param length
* the length of the stream
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
* @param length
* of the stream
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateAsciiStream(String columnName, java.io.InputStream x, int length) throws SQLException {
updateAsciiStream(findColumn(columnName), x, length);
}
/**
* JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
updateBigDecimal(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a binary stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
* @param length
* the length of the stream
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a binary stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
* @param length
* of the stream
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {
updateBinaryStream(findColumn(columnName), x, length);
}
/**
* @see ResultSetInternalMethods#updateBlob(int, Blob)
*/
public void updateBlob(int arg0, java.sql.Blob arg1) throws SQLException {
throw new NotUpdatable();
}
/**
* @see ResultSetInternalMethods#updateBlob(String, Blob)
*/
public void updateBlob(String arg0, java.sql.Blob arg1) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateBoolean(int columnIndex, boolean x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateBoolean(String columnName, boolean x) throws SQLException {
updateBoolean(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateByte(int columnIndex, byte x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateByte(String columnName, byte x) throws SQLException {
updateByte(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateBytes(int columnIndex, byte[] x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateBytes(String columnName, byte[] x) throws SQLException {
updateBytes(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a character stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
* @param length
* the length of the stream
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a character stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName
* the name of the column
* @param reader
* the stream to update the column with
* @param length
* of the stream
*
* @throws SQLException
* if a database-access error occurs
*/
public void updateCharacterStream(String columnName, java.io.Reader reader, int length) throws SQLException {
updateCharacterStream(findColumn(columnName), reader, length);
}
/**
* @see ResultSetInternalMethods#updateClob(int, Clob)
*/
public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* @see ResultSetInternalMethods#updateClob(String, Clob)
*/
public void updateClob(String columnName, java.sql.Clob clob) throws SQLException {
updateClob(findColumn(columnName), clob);
}
/**
* JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateDate(String columnName, java.sql.Date x) throws SQLException {
updateDate(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateDouble(int columnIndex, double x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a double value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateDouble(String columnName, double x) throws SQLException {
updateDouble(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a float value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateFloat(int columnIndex, float x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a float value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateFloat(String columnName, float x) throws SQLException {
updateFloat(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with an integer value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateInt(int columnIndex, int x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an integer value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateInt(String columnName, int x) throws SQLException {
updateInt(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a long value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateLong(int columnIndex, long x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a long value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateLong(String columnName, long x) throws SQLException {
updateLong(findColumn(columnName), x);
}
/**
* JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateNull(int columnIndex) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a null value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateNull(String columnName) throws SQLException {
updateNull(findColumn(columnName));
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateObject(int columnIndex, Object x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
* @param scale
* For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
* this is the number of digits after the decimal. For all other
* types this value will be ignored.
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateObject(String columnName, Object x) throws SQLException {
updateObject(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
* @param scale
* For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
* this is the number of digits after the decimal. For all other
* types this value will be ignored.
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateObject(String columnName, Object x, int scale) throws SQLException {
updateObject(findColumn(columnName), x);
}
/**
* @see ResultSetInternalMethods#updateRef(int, Ref)
*/
public void updateRef(int arg0, Ref arg1) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* @see ResultSetInternalMethods#updateRef(String, Ref)
*/
public void updateRef(String arg0, Ref arg1) throws SQLException {
throw SQLError.createSQLFeatureNotSupportedException();
}
/**
* JDBC 2.0 Update the underlying database with the new contents of the
* current row. Cannot be called when on the insert row.
*
* @exception SQLException
* if a database-access error occurs, or if called when on
* the insert row
* @throws NotUpdatable
*/
public void updateRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a short value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateShort(int columnIndex, short x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a short value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateShort(String columnName, short x) throws SQLException {
updateShort(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a String value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateString(int columnIndex, String x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a String value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateString(String columnName, String x) throws SQLException {
updateString(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateTime(String columnName, java.sql.Time x) throws SQLException {
updateTime(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex
* the first column is 1, the second is 2, ...
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
* @throws NotUpdatable
*/
public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the database.
*
* @param columnName
* the name of the column
* @param x
* the new column value
*
* @exception SQLException
* if a database-access error occurs
*/
public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {
updateTimestamp(findColumn(columnName), x);
}
/**
* A column may have the value of SQL NULL; wasNull() reports whether the
* last column read had this special value. Note that you must first call
* getXXX on a column to try to read its value and then call wasNull() to
* find if the value was SQL NULL
*
* @return true if the last column read was SQL NULL
*
* @exception SQLException
* if a database access error occurred
*/
public boolean wasNull() throws SQLException {
return this.wasNullFlag;
}
protected Calendar getGmtCalendar() {
// Worst case we allocate this twice and the other gets GC'd,
// however prevents deadlock
if (this.gmtCalendar == null) {
this.gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
}
return this.gmtCalendar;
}
protected ExceptionInterceptor getExceptionInterceptor() {
return this.exceptionInterceptor;
}
}