/*
Copyright (C) 2002 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.mysql.jdbc;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Array;
import java.sql.Clob;
import java.sql.Date;
import java.sql.Ref;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
/**
* A ResultSet provides access to a table of data generated by executing a
* Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order.
*
* <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>
*
* @author Mark Matthews
* @version $Id: ResultSet.java,v 1.18.2.23 2003/12/24 05:16:25 mmatthew Exp $
*
* @see ResultSetMetaData
* @see java.sql.ResultSet
*/
public class ResultSet implements java.sql.ResultSet {
/**
* This method ends up being staticly synchronized, so just store our own
* copy....
*/
private final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault();
/** The Connection instance that created us */
protected com.mysql.jdbc.Connection connection; // The connection that created us
/** Map column names (and all of their permutations) to column indices */
protected Map columnNameToIndex = null;
/** Map of fully-specified column names to column indices */
protected Map fullColumnNameToIndex = null;
/** The actual rows */
protected RowData rowData; // The results
/** The warning chain */
protected java.sql.SQLWarning warningChain = null;
/** The statement that created us */
protected com.mysql.jdbc.Statement owningStatement;
/** The catalog that was in use when we were created */
protected String catalog = null;
/**
* Any info message from the server that was created while generating this
* result set (if 'info parsing' is enabled for the connection).
*/
protected String serverInfo = null;
/** The fields for this result set */
protected Field[] fields; // The fields
/** Pointer to current row data */
protected byte[][] thisRow; // Values for current row
/** Are we in the middle of doing updates to the current row? */
protected boolean doingUpdates = false;
/** Has this result set been closed? */
protected boolean isClosed = false;
/** Are we on the insert row? */
protected boolean onInsertRow = false;
/**
* Do we actually contain rows, or just information about
* UPDATE/INSERT/DELETE?
*/
protected boolean reallyResult = false;
/** Did the previous value retrieval find a NULL? */
protected boolean wasNullFlag = false;
/**
* First character of the query that created this result set...Used to
* determine whether or not to parse server info messages in certain
* circumstances.
*/
protected char firstCharOfQuery;
/** The current row #, -1 == before start of result set */
protected int currentRow = -1; // Cursor to current row;
/** The direction to fetch rows (always FETCH_FORWARD) */
protected int fetchDirection = FETCH_FORWARD;
/** The number of rows to fetch in one go... */
protected int fetchSize = 0;
/** Are we read-only or updatable? */
protected int resultSetConcurrency = 0;
/** Are we scroll-sensitive/insensitive? */
protected int resultSetType = 0;
/** How many rows were affected by UPDATE/INSERT/DELETE? */
protected long updateCount;
// 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.
//
/** Value generated for AUTO_INCREMENT columns */
protected long updateId = -1;
private Calendar fastDateCal = null;
private boolean hasBuiltIndexMapping = false;
private boolean useStrictFloatingPoint = false;
/**
* Create a result set for an executeUpdate statement.
*
* @param updateCount the number of rows affected by the update
* @param updateID the autoincrement value (if any)
*/
public ResultSet(long updateCount, long updateID) {
this.updateCount = updateCount;
this.updateId = updateID;
reallyResult = false;
fields = new Field[0];
}
/**
* Create a new ResultSet
*
* @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.
*
* @throws SQLException if an error occurs
*/
public ResultSet(String catalog, Field[] fields, RowData tuples,
com.mysql.jdbc.Connection conn) throws SQLException {
this(fields, tuples);
setConnection(conn);
this.catalog = catalog;
}
/**
* Creates a new ResultSet object.
*
* @param fields DOCUMENT ME!
* @param tuples DOCUMENT ME!
*
* @throws SQLException DOCUMENT ME!
*/
public ResultSet(Field[] fields, RowData tuples) throws SQLException {
//_currentRow = -1;
this.fields = fields;
this.rowData = tuples;
this.updateCount = (long) rowData.size();
if (Driver.DEBUG) {
System.out.println("Retrieved " + updateCount + " rows");
}
this.reallyResult = true;
// Check for no results
if (this.rowData.size() > 0) {
//_thisRow = _rows.next();
if (this.updateCount == 1) {
if (this.thisRow == null) {
//_currentRow = -1;
this.rowData.close(); // empty result set
this.updateCount = -1;
}
}
} else {
this.thisRow = null;
}
this.rowData.setOwner(this);
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "isAfterLast", args);
}
boolean b = rowData.isAfterLast();
if (Driver.TRACE) {
Debug.returnValue(this, "isAfterLast", new Boolean(b));
}
return b;
}
/**
* JDBC 2.0 Get an array column.
*
* @param i the first column is 1, the second is 2, ...
*
* @return an object representing an SQL array
*
* @throws SQLException if a database error occurs
* @throws NotImplemented DOCUMENT ME!
*/
public java.sql.Array getArray(int i) throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0 Get an array column.
*
* @param colName the column name
*
* @return an object representing an SQL array
*
* @throws SQLException if a database error occurs
* @throws NotImplemented DOCUMENT ME!
*/
public java.sql.Array getArray(String colName) throws SQLException {
throw new NotImplemented();
}
/**
* A column value can be retrieved as a stream of ASCII characters and then
* read in chunks from the stream. This method is particulary suitable
* for retrieving large LONGVARCHAR values. The JDBC driver will do any
* necessary conversion from the database format into ASCII.
*
* <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 java.sql.SQLException if a database access error occurs
*
* @see getBinaryStream
*/
public InputStream getAsciiStream(int columnIndex)
throws java.sql.SQLException {
checkRowPos();
return getBinaryStream(columnIndex);
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public InputStream getAsciiStream(String columnName)
throws java.sql.SQLException {
return getAsciiStream(findColumn(columnName));
}
//---------------------------------------------------------------------
// Traversal/Positioning
//---------------------------------------------------------------------
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "isBeforeFirst", args);
}
boolean b = rowData.isBeforeFirst();
if (Driver.TRACE) {
Debug.returnValue(this, "isBeforeFirst", new Boolean(b));
}
return b;
}
/**
* 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 java.sql.SQLException if a database access error occurs
*/
public BigDecimal getBigDecimal(int columnIndex, int scale)
throws java.sql.SQLException {
String stringVal = getString(columnIndex);
BigDecimal val;
if (stringVal != null) {
if (stringVal.length() == 0) {
val = new BigDecimal(0);
return val.setScale(scale);
}
try {
val = new BigDecimal(stringVal);
} catch (NumberFormatException ex) {
throw new java.sql.SQLException("Bad format for BigDecimal '"
+ stringVal + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
try {
return val.setScale(scale);
} catch (ArithmeticException ex) {
throw new java.sql.SQLException("Bad format for BigDecimal '"
+ stringVal + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
return null;
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
* @param scale DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public BigDecimal getBigDecimal(String columnName, int scale)
throws java.sql.SQLException {
return getBigDecimal(findColumn(columnName), scale);
}
/**
* JDBC 2.0 Get the value of a column in the current row as a
* java.math.BigDecimal object.
*
* @param columnIndex the first column is 1, the second is 2, ...
*
* @return the column value (full precision); if the value is SQL NULL, the
* result is null
*
* @exception SQLException if a database-access error occurs.
* @throws java.sql.SQLException DOCUMENT ME!
*/
public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
String stringVal = getString(columnIndex);
BigDecimal val;
if (stringVal != null) {
if (stringVal.length() == 0) {
val = new BigDecimal(0);
return val;
}
try {
val = new BigDecimal(stringVal);
return val;
} catch (NumberFormatException ex) {
throw new java.sql.SQLException("Bad format for BigDecimal '"
+ stringVal + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
return null;
}
/**
* JDBC 2.0 Get the value of a column in the current row as a
* java.math.BigDecimal object.
*
* @param columnName the name of the column to retrieve the value from
*
* @return the BigDecimal value in the column
*
* @throws SQLException if an error occurs
*/
public BigDecimal getBigDecimal(String columnName)
throws SQLException {
return getBigDecimal(findColumn(columnName));
}
/**
* A column value can also be retrieved as a binary strea. This method is
* suitable for retrieving LONGVARBINARY values.
*
* @param columnIndex the first column is 1, the second is 2...
*
* @return a Java InputStream that delivers the database column value as a
* stream of bytes. If the value is SQL NULL, then the result is
* null
*
* @exception java.sql.SQLException if a database access error occurs
*
* @see getAsciiStream
* @see getUnicodeStream
*/
public InputStream getBinaryStream(int columnIndex)
throws java.sql.SQLException {
checkRowPos();
byte[] b = getBytes(columnIndex);
if (b != null) {
return new ByteArrayInputStream(b);
}
return null;
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public InputStream getBinaryStream(String columnName)
throws java.sql.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.
* @throws java.sql.SQLException DOCUMENT ME!
*/
public java.sql.Blob getBlob(int columnIndex) throws SQLException {
checkRowPos();
if ((columnIndex < 1) || (columnIndex > fields.length)) {
throw new java.sql.SQLException("Column Index out of range ( "
+ columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
}
try {
if (thisRow[columnIndex - 1] == null) {
wasNullFlag = true;
} else {
wasNullFlag = false;
}
} catch (NullPointerException ex) {
wasNullFlag = true;
}
if (wasNullFlag) {
return null;
}
return new Blob(thisRow[columnIndex - 1]);
}
/**
* 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 java.sql.SQLException if a database access error occurs
*/
public boolean getBoolean(int columnIndex) throws java.sql.SQLException {
String stringVal = getString(columnIndex);
if ((stringVal != null) && (stringVal.length() > 0)) {
int c = Character.toLowerCase(stringVal.charAt(0));
return ((c == 't') || (c == 'y') || (c == '1')
|| stringVal.equals("-1"));
}
return false;
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public boolean getBoolean(String columnName) throws java.sql.SQLException {
return getBoolean(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a Java byte.
*
* @param columnIndex the first column is 1, the second is 2,...
*
* @return the column value; 0 if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public byte getByte(int columnIndex) throws java.sql.SQLException {
checkRowPos();
try {
if (thisRow[columnIndex - 1] == null) {
wasNullFlag = true;
} else {
wasNullFlag = false;
}
} catch (NullPointerException E) {
wasNullFlag = true;
}
if (wasNullFlag) {
return 0;
}
Field field = fields[columnIndex - 1];
switch (field.getMysqlType()) {
case MysqlDefs.FIELD_TYPE_DECIMAL:
case MysqlDefs.FIELD_TYPE_TINY:
case MysqlDefs.FIELD_TYPE_SHORT:
case MysqlDefs.FIELD_TYPE_LONG:
case MysqlDefs.FIELD_TYPE_FLOAT:
case MysqlDefs.FIELD_TYPE_DOUBLE:
case MysqlDefs.FIELD_TYPE_LONGLONG:
case MysqlDefs.FIELD_TYPE_INT24:
try {
String stringVal = getString(columnIndex);
int decimalIndex = stringVal.indexOf(".");
// Strip off the decimals
if (decimalIndex != -1) {
stringVal = stringVal.substring(0, decimalIndex);
}
return Byte.parseByte(stringVal);
} catch (NumberFormatException NFE) {
throw new SQLException("Value '" + getString(columnIndex)
+ "' is out of range [-127,127]", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
default:
try {
String stringVal = getString(columnIndex);
int decimalIndex = stringVal.indexOf(".");
// Strip off the decimals
if (decimalIndex != -1) {
stringVal = stringVal.substring(0, decimalIndex);
}
return Byte.parseByte(stringVal);
} catch (NumberFormatException NFE) {
throw new SQLException("Value '" + getString(columnIndex)
+ "' is out of range [-127,127]", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
// FIXME: JDBC-Compliance test is broken, wants to convert string->byte(num)
//return _thisRow[columnIndex - 1][0];
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public byte getByte(String columnName) throws java.sql.SQLException {
return getByte(findColumn(columnName));
}
/**
* 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 java.sql.SQLException if a database access error occurs
*/
public byte[] getBytes(int columnIndex) throws java.sql.SQLException {
checkRowPos();
try {
if (thisRow[columnIndex - 1] == null) {
wasNullFlag = true;
} else {
wasNullFlag = false;
}
} catch (NullPointerException E) {
wasNullFlag = true;
} catch (ArrayIndexOutOfBoundsException aioobEx) {
throw new java.sql.SQLException("Column Index out of range ( "
+ columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
}
if (wasNullFlag) {
return null;
} else {
return thisRow[columnIndex - 1];
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public byte[] getBytes(String columnName) throws java.sql.SQLException {
return getBytes(findColumn(columnName));
}
//--------------------------JDBC 2.0-----------------------------------
//---------------------------------------------------------------------
// Getter's and Setter's
//---------------------------------------------------------------------
/**
* 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 {
String stringVal = getString(columnIndex);
if (stringVal != null) {
return new StringReader(stringVal);
} else {
return null;
}
}
/**
* 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));
}
/**
* 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 {
return new com.mysql.jdbc.Clob(getString(i));
}
/**
* JDBC 2.0 Get a CLOB column.
*
* @param colName the column name
*
* @return an object representing a CLOB
*
* @throws SQLException if an error occurs
*/
public java.sql.Clob getClob(String colName) throws SQLException {
return getClob(findColumn(colName));
}
/**
* JDBC 2.0 Return the concurrency of this result set. The concurrency
* used is determined by the statement that created the result set.
*
* @return the concurrency type, CONCUR_READ_ONLY, etc.
*
* @throws SQLException if a database-access error occurs
*/
public int getConcurrency() throws SQLException {
return (CONCUR_READ_ONLY);
}
/**
* DOCUMENT ME!
*
* @param conn the connection that created this result set.
*/
public void setConnection(com.mysql.jdbc.Connection conn) {
this.connection = conn;
if (connection != null) {
useStrictFloatingPoint = connection.useStrictFloatingPoint();
}
}
/**
* 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
* java.sql.SQLException is thrown.
* </p>
*
* @return the ResultSet's SQL cursor name.
*
* @exception java.sql.SQLException if a database access error occurs
*/
public String getCursorName() throws java.sql.SQLException {
throw new java.sql.SQLException("Positioned Update not supported.",
"S1C00");
}
/**
* Get the value of a column in the current row as a java.sql.Date object
*
* @param columnIndex the first column is 1, the second is 2...
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
*/
public java.sql.Date getDate(int columnIndex) throws java.sql.SQLException {
return getDate(columnIndex, null);
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public java.sql.Date getDate(String columnName)
throws java.sql.SQLException {
return getDate(findColumn(columnName));
}
/**
* JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
* object. Use the calendar to construct an appropriate millisecond value
* for the Date, if the underlying database doesn't store timezone
* information.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param cal the calendar to use in constructing the date
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException if a database-access error occurs.
* @throws java.sql.SQLException DOCUMENT ME!
*/
public java.sql.Date getDate(int columnIndex, Calendar cal)
throws SQLException {
Integer year = null;
Integer month = null;
Integer day = null;
String stringVal = "";
try {
stringVal = getString(columnIndex);
if (stringVal == null) {
return null;
} else {
int length = stringVal.length();
if ((length > 0) && (stringVal.charAt(0) == '0')
&& (stringVal.equals("0000-00-00")
|| stringVal.equals("0000-00-00 00:00:00")
|| stringVal.equals("00000000000000")
|| stringVal.equals("0"))) {
wasNullFlag = true;
return null;
} else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
// Convert from TIMESTAMP
switch (length) {
case 14:
case 8: {
year = new Integer(stringVal.substring(0, 4));
month = new Integer(stringVal.substring(4, 6));
day = new Integer(stringVal.substring(6, 8));
return fastDateCreate(cal, year.intValue() - 1900,
month.intValue() - 1, day.intValue());
}
case 12:
case 10:
case 6: {
year = new Integer(stringVal.substring(0, 2));
if (year.intValue() <= 69) {
year = new Integer(year.intValue() + 100);
}
month = new Integer(stringVal.substring(2, 4));
day = new Integer(stringVal.substring(4, 6));
return fastDateCreate(cal, year.intValue(),
month.intValue() - 1, day.intValue());
}
case 4: {
year = new Integer(stringVal.substring(0, 4));
if (year.intValue() <= 69) {
year = new Integer(year.intValue() + 100);
}
month = new Integer(stringVal.substring(2, 4));
return fastDateCreate(cal, year.intValue(),
month.intValue() - 1, 1);
}
case 2: {
year = new Integer(stringVal.substring(0, 2));
if (year.intValue() <= 69) {
year = new Integer(year.intValue() + 100);
}
return fastDateCreate(cal, year.intValue(), 0, 1);
}
default:
throw new SQLException("Bad format for Date '"
+ stringVal + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
} /* endswitch */
} else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
year = new Integer(stringVal.substring(0, 4));
return fastDateCreate(cal, year.intValue() - 1900, 0, 1);
} else {
if (length < 10) {
throw new SQLException("Bad format for Date '"
+ stringVal + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
year = new Integer(stringVal.substring(0, 4));
month = new Integer(stringVal.substring(5, 7));
day = new Integer(stringVal.substring(8, 10));
}
return fastDateCreate(cal, year.intValue() - 1900,
month.intValue() - 1, day.intValue());
}
} catch (Exception e) {
throw new java.sql.SQLException("Cannot convert value '"
+ stringVal + "' from column " + columnIndex + "(" + stringVal
+ " ) to DATE.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* 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(columnName);
}
/**
* 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 java.sql.SQLException if a database access error occurs
*/
public double getDouble(int columnIndex) throws java.sql.SQLException {
try {
return getDoubleInternal(columnIndex);
} catch (NumberFormatException E) {
throw new java.sql.SQLException("Bad format for number '"
+ new String(thisRow[columnIndex - 1]) + "' in column "
+ columnIndex + "(" + fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public double getDouble(String columnName) throws java.sql.SQLException {
return getDouble(findColumn(columnName));
}
/**
* JDBC 2.0 Give a hint as to the direction in which the rows in this
* result set will be processed. The initial value is determined by the
* statement that produced the result set. The fetch direction may be
* changed at any time.
*
* @param direction the direction to fetch rows in.
*
* @exception SQLException if a database-access error occurs, or the result
* set type is TYPE_FORWARD_ONLY and direction is not
* FETCH_FORWARD. MM.MySQL actually ignores this, because it
* has the whole result set anyway, so the direction is
* immaterial.
*/
public void setFetchDirection(int direction) throws SQLException {
if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE)
&& (direction != FETCH_UNKNOWN)) {
throw new SQLException("Illegal value for fetch direction", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
} else {
fetchDirection = direction;
}
}
/**
* JDBC 2.0 Returns the fetch direction for this result set.
*
* @return the fetch direction for this result set.
*
* @exception SQLException if a database-access error occurs
*/
public int getFetchDirection() throws SQLException {
return fetchDirection;
}
/**
* JDBC 2.0 Give the JDBC driver a hint as to the number of rows that
* should be fetched from the database when more rows are needed for this
* result set. If the fetch size specified is zero, then the JDBC driver
* ignores the value, and is free to make its own best guess as to what
* the fetch size should be. The default value is set by the statement
* that creates the result set. The fetch size may be changed at any
* time.
*
* @param rows the number of rows to fetch
*
* @exception SQLException if a database-access error occurs, or the
* condition 0 <= rows <= this.getMaxRows() is not
* satisfied. Currently ignored by this driver.
*/
public void setFetchSize(int rows) throws SQLException {
if (rows < 0) { /* || rows > getMaxRows()*/
throw new SQLException("Value must be between 0 and getMaxRows()",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
fetchSize = rows;
}
/**
* JDBC 2.0 Return the fetch size for this result set.
*
* @return the fetch size for this result set.
*
* @exception SQLException if a database-access error occurs
*/
public int getFetchSize() throws SQLException {
return fetchSize;
}
/**
* JDBC 2.0
*
* <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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "isFirst", args);
}
boolean b = rowData.isFirst();
if (Driver.TRACE) {
Debug.returnValue(this, "isFirst", new Boolean(b));
}
return b;
}
/**
* 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 java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public float getFloat(int columnIndex) throws java.sql.SQLException {
checkRowPos();
String val = null;
try {
val = getString(columnIndex);
if ((val != null) && (val.length() != 0)) {
float f = Float.parseFloat(val);
return f;
} else {
return 0;
}
} catch (NumberFormatException nfe) {
try {
// To do: warn on under/overflow?
return (float) Double.parseDouble(val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw new SQLException("Invalid value for getFloat() - '" + val
+ "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public float getFloat(String columnName) throws java.sql.SQLException {
return getFloat(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a Java int.
*
* @param columnIndex the first column is 1, the second is 2,...
*
* @return the column value; 0 if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public int getInt(int columnIndex) throws java.sql.SQLException {
String val = null;
try {
val = getString(columnIndex);
if ((val != null) && (val.length() != 0)) {
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
&& (val.indexOf(".") == -1)) {
return Integer.parseInt(val);
} else {
// Convert floating point
return (int) (Double.parseDouble(val));
}
} else {
return 0;
}
} catch (NumberFormatException nfe) {
try {
// To do: warn on under/overflow?
return (int) Double.parseDouble(val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw new SQLException("Invalid value for getInt() - '" + val + "'",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public int getInt(String columnName) throws java.sql.SQLException {
return getInt(findColumn(columnName));
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "isLast", args);
}
boolean b = rowData.isLast();
if (Driver.TRACE) {
Debug.returnValue(this, "relative", new Boolean(b));
}
return b;
}
/**
* 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 java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public long getLong(int columnIndex) throws java.sql.SQLException {
checkRowPos();
String val = null;
try {
val = getString(columnIndex);
if ((val != null) && (val.length() != 0)) {
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
return Long.parseLong(val);
} else {
// Convert floating point
return Double.doubleToLongBits(Double.parseDouble(val));
}
} else {
return 0;
}
} catch (NumberFormatException nfe) {
try {
// To do: warn on under/overflow?
return (long) Double.parseDouble(val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw new SQLException("Invalid value for getLong() - '" + val
+ "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public long getLong(String columnName) throws java.sql.SQLException {
return getLong(findColumn(columnName));
}
/**
* The numbers, types and properties of a ResultSet's columns are provided
* by the getMetaData method
*
* @return a description of the ResultSet's columns
*
* @exception java.sql.SQLException if a database access error occurs
*/
public java.sql.ResultSetMetaData getMetaData()
throws java.sql.SQLException {
return new com.mysql.jdbc.ResultSetMetaData(fields);
}
/**
* 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 java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public Object getObject(int columnIndex) throws java.sql.SQLException {
checkRowPos();
if (Driver.TRACE) {
Object[] args = { new Integer(columnIndex) };
Debug.methodCall(this, "getObject", args);
}
try {
if (thisRow[columnIndex - 1] == null) {
wasNullFlag = true;
return null;
}
} catch (ArrayIndexOutOfBoundsException aioobEx) {
throw new java.sql.SQLException("Column Index out of range ( "
+ columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
}
wasNullFlag = false;
Field field;
field = fields[columnIndex - 1];
switch (field.getSQLType()) {
case Types.BIT:
return new Boolean(getBoolean(columnIndex));
case Types.TINYINT:
return new Integer(getInt(columnIndex));
case Types.SMALLINT:
return new Integer(getInt(columnIndex));
case Types.INTEGER:
if (field.isUnsigned()) {
return new Long(getLong(columnIndex));
} else {
return new Integer(getInt(columnIndex));
}
case Types.BIGINT:
if (field.isUnsigned()) {
return getBigDecimal(columnIndex);
} else {
return new Long(getLong(columnIndex));
}
case Types.DECIMAL:
case Types.NUMERIC:
String stringVal = getString(columnIndex);
BigDecimal val;
if (stringVal != null) {
if (stringVal.length() == 0) {
val = new BigDecimal(0);
return val;
}
try {
val = new BigDecimal(stringVal);
} catch (NumberFormatException ex) {
throw new java.sql.SQLException(
"Bad format for BigDecimal '" + stringVal
+ "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
return val;
} else {
return null;
}
case Types.REAL:
return new Float(getFloat(columnIndex));
case Types.FLOAT:
case Types.DOUBLE:
return new Double(getDouble(columnIndex));
case Types.CHAR:
case Types.VARCHAR:
case Types.LONGVARCHAR:
return getString(columnIndex);
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
if (!field.isBlob()) {
return getString(columnIndex);
} else if (!field.isBinary()) {
return getString(columnIndex);
} else {
byte[] data = getBytes(columnIndex);
Object obj = data;
if ((data != null) && (data.length >= 2)) {
if ((data[0] == -84) && (data[1] == -19)) {
// Serialized object?
try {
ByteArrayInputStream bytesIn = new ByteArrayInputStream(data);
ObjectInputStream objIn = new ObjectInputStream(bytesIn);
obj = objIn.readObject();
objIn.close();
bytesIn.close();
} catch (ClassNotFoundException cnfe) {
throw new SQLException("Class not found: "
+ cnfe.toString()
+ " while reading serialized object");
} catch (IOException ex) {
obj = data; // not serialized?
}
}
}
return obj;
}
case Types.DATE:
return getDate(columnIndex);
case Types.TIME:
return getTime(columnIndex);
case Types.TIMESTAMP:
return getTimestamp(columnIndex);
default:
return getString(columnIndex);
}
}
/**
* Get the value of a column in the current row as a Java object
*
* <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 java.sql.SQLException if a database access error occurs
*/
public Object getObject(String columnName) throws java.sql.SQLException {
return getObject(findColumn(columnName));
}
/**
* JDBC 2.0 Returns the value of column i as a Java object. Use the map to
* determine the class from which to construct data of SQL structured and
* distinct types.
*
* @param i the first column is 1, the second is 2, ...
* @param map the mapping from SQL type names to Java classes
*
* @return an object representing the SQL value
*
* @throws SQLException because this is not implemented
*/
public Object getObject(int i, java.util.Map map) throws SQLException {
return getObject(i);
}
/**
* JDBC 2.0 Returns the value of column i as a Java object. Use the map to
* determine the class from which to construct data of SQL structured and
* distinct types.
*
* @param colName the column name
* @param map the mapping from SQL type names to Java classes
*
* @return an object representing the SQL value
*
* @throws SQLException as this is not implemented
*/
public Object getObject(String colName, java.util.Map map)
throws SQLException {
return getObject(findColumn(colName), map);
}
/**
* JDBC 2.0 Get a REF(<structured-type>) column.
*
* @param i the first column is 1, the second is 2, ...
*
* @return an object representing data of an SQL REF type
*
* @throws SQLException as this is not implemented
* @throws NotImplemented DOCUMENT ME!
*/
public java.sql.Ref getRef(int i) throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0 Get a REF(<structured-type>) column.
*
* @param colName the column name
*
* @return an object representing data of an SQL REF type
*
* @throws SQLException as this method is not implemented.
* @throws NotImplemented DOCUMENT ME!
*/
public java.sql.Ref getRef(String colName) throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0
*
* <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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "getRow", args);
}
int currentRow = rowData.getCurrentRowNumber();
int row = 0;
// Non-dynamic result sets can be interrogated
// for this information
if (!rowData.isDynamic()) {
if ((currentRow < 0) || rowData.isAfterLast() || rowData.isEmpty()) {
row = 0;
} else {
row = currentRow + 1;
}
} else {
// dynamic (streaming) can not
row = currentRow + 1;
}
if (Driver.TRACE) {
Debug.returnValue(this, "getRow", new Integer(row));
}
if (Driver.TRACE) {
Debug.returnValue(this, "getRow", new Integer(row));
}
return row;
}
/**
* Get the value of a column in the current row as a Java short.
*
* @param columnIndex the first column is 1, the second is 2,...
*
* @return the column value; 0 if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public short getShort(int columnIndex) throws java.sql.SQLException {
checkRowPos();
String val = null;
try {
val = getString(columnIndex);
if ((val != null) && (val.length() != 0)) {
if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
&& (val.indexOf(".") == -1)) {
return Short.parseShort(val);
} else {
// Convert floating point
return (short) (Double.parseDouble(val));
}
} else {
return 0;
}
} catch (NumberFormatException nfe) {
try {
// To do: warn on under/overflow?
return (short) Double.parseDouble(val);
} catch (NumberFormatException newNfe) {
; // ignore, it's not a number
}
throw new SQLException("Invalid value for getShort() - '" + val
+ "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public short getShort(String columnName) throws java.sql.SQLException {
return getShort(findColumn(columnName));
}
/**
* JDBC 2.0 Return the Statement that produced the ResultSet.
*
* @return the Statment that produced the result set, or null if the result
* was produced some other way.
*
* @exception SQLException if a database-access error occurs
*/
public java.sql.Statement getStatement() throws SQLException {
return (java.sql.Statement) owningStatement;
}
/**
* Get the value of a column in the current row as a Java String
*
* @param columnIndex the first column is 1, the second is 2...
*
* @return the column value, null for SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
* @throws SQLException DOCUMENT ME!
*/
public String getString(int columnIndex) throws java.sql.SQLException {
checkRowPos();
if (fields == null) {
throw new java.sql.SQLException("Query generated no fields for ResultSet",
SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
}
try {
if (thisRow[columnIndex - 1] == null) {
wasNullFlag = true;
return null;
} else {
wasNullFlag = false;
}
} catch (NullPointerException E) {
wasNullFlag = true;
return null;
} catch (ArrayIndexOutOfBoundsException aioobEx) {
throw new java.sql.SQLException("Column Index out of range ( "
+ columnIndex + " > " + fields.length + ").", SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
}
String stringVal = null;
columnIndex--; // JDBC is 1-based, Java is not !?
if ((connection != null) && connection.useUnicode()) {
try {
String encoding = this.fields[columnIndex].getCharacterSet();
if (encoding == null) {
stringVal = new String(thisRow[columnIndex]);
} else {
SingleByteCharsetConverter converter = this.connection.getCharsetConverter(encoding);
if (converter != null) {
stringVal = converter.toString(thisRow[columnIndex]);
} else {
stringVal = new String(thisRow[columnIndex], encoding);
}
}
} catch (java.io.UnsupportedEncodingException E) {
throw new SQLException("Unsupported character encoding '"
+ connection.getEncoding() + "'.", SQLError.SQL_STATE_GENERAL_ERROR);
}
} else {
stringVal = StringUtils.toAsciiString(thisRow[columnIndex]);
}
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 java.sql.SQLException if a database access error occurs
*/
public String getString(String columnName) throws java.sql.SQLException {
return getString(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a java.sql.Time object
*
* @param columnIndex the first column is 1, the second is 2...
*
* @return the column value; null if SQL NULL
*
* @throws java.sql.SQLException if a database access error occurs
*/
public Time getTime(int columnIndex) throws java.sql.SQLException {
return getTimeInternal(columnIndex, DEFAULT_TIMEZONE);
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
*
* @param columnName is the SQL name of the column
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @throws java.sql.SQLException if a database-access error occurs.
*/
public Time getTime(String columnName) throws java.sql.SQLException {
return getTime(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
* Use the calendar to construct an appropriate millisecond value for the
* Time, if the underlying database doesn't store timezone information.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param cal the calendar to use in constructing the time
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Time getTime(int columnIndex, Calendar cal)
throws SQLException {
return getTimeInternal(columnIndex, cal.getTimeZone());
}
/**
* Get the value of a column in the current row as a java.sql.Time object.
* Use the calendar to construct an appropriate millisecond value for the
* Time, if the underlying database doesn't store timezone information.
*
* @param columnName is the SQL name of the column
* @param cal the calendar to use in constructing the time
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Time getTime(String columnName, Calendar cal)
throws SQLException {
return getTime(findColumn(columnName), cal);
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object
*
* @param columnIndex the first column is 1, the second is 2...
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
*/
public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException {
return getTimestampInternal(columnIndex, DEFAULT_TIMEZONE);
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public Timestamp getTimestamp(String columnName)
throws java.sql.SQLException {
return getTimestamp(findColumn(columnName));
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object. Use the calendar to construct an appropriate millisecond value
* for the Timestamp, if the underlying database doesn't store timezone
* information.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param cal the calendar to use in constructing the timestamp
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
throws SQLException {
return getTimestampInternal(columnIndex, cal.getTimeZone());
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object. Use the calendar to construct an appropriate millisecond value
* for the Timestamp, if the underlying database doesn't store timezone
* information.
*
* @param columnName is the SQL name of the column
* @param cal the calendar to use in constructing the timestamp
*
* @return the column value; if the value is SQL NULL, the result is null
*
* @exception SQLException if a database-access error occurs.
*/
public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)
throws SQLException {
return getTimestamp(findColumn(columnName), cal);
}
/**
* JDBC 2.0 Return the type of this result set. The type is determined
* based on the statement that created the result set.
*
* @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
* TYPE_SCROLL_SENSITIVE
*
* @exception SQLException if a database-access error occurs
*/
public int getType() throws SQLException {
return resultSetType;
}
/**
* @see ResultSet#getURL(int)
*/
public URL getURL(int colIndex) throws SQLException {
String val = getString(colIndex);
if (val == null) {
return null;
} else {
try {
return new URL(val);
} catch (MalformedURLException mfe) {
throw new SQLException("Malformed URL '" + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
}
/**
* @see ResultSet#getURL(String)
*/
public URL getURL(String colName) throws SQLException {
String val = getString(colName);
if (val == null) {
return null;
} else {
try {
return new URL(val);
} catch (MalformedURLException mfe) {
throw new SQLException("Malformed URL '" + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
}
/**
* 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 java.sql.SQLException if a database access error occurs
*
* @see getAsciiStream
* @see getBinaryStream
*/
public InputStream getUnicodeStream(int columnIndex)
throws java.sql.SQLException {
checkRowPos();
return getBinaryStream(columnIndex);
}
/**
* DOCUMENT ME!
*
* @param columnName DOCUMENT ME!
*
* @return DOCUMENT ME!
*
* @throws java.sql.SQLException DOCUMENT ME!
*/
public InputStream getUnicodeStream(String columnName)
throws java.sql.SQLException {
return getUnicodeStream(findColumn(columnName));
}
/**
* The first warning reported by calls on this ResultSet is returned.
* Subsequent ResultSet warnings will be chained to this
* java.sql.SQLWarning.
*
* <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 java.sql.SQLException if a database access error occurs.
*/
public java.sql.SQLWarning getWarnings() throws java.sql.SQLException {
return warningChain;
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { new Integer(row) };
Debug.methodCall(this, "absolute", args);
}
checkClosed();
boolean b;
if (rowData.size() == 0) {
b = false;
} else {
if (row == 0) {
throw new SQLException("Cannot absolute position to row 0",
SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
if (row == 1) {
b = first();
} else if (row == -1) {
b = last();
} else if (row > rowData.size()) {
afterLast();
b = false;
} else {
if (row < 0) {
// adjust to reflect after end of result set
int newRowPosition = rowData.size() + row + 1;
if (newRowPosition <= 0) {
beforeFirst();
b = false;
} else {
b = absolute(newRowPosition);
}
} else {
row--; // adjust for index difference
rowData.setCurrentRow(row);
thisRow = (byte[][]) rowData.getAt(row);
b = true;
}
}
}
if (Driver.TRACE) {
Debug.returnValue(this, "absolute", new Boolean(b));
}
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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "afterLast", args);
}
checkClosed();
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
if (rowData.size() != 0) {
rowData.afterLast();
thisRow = null;
}
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "beforeFirst", args);
}
checkClosed();
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
if (rowData.size() == 0) {
return;
} else {
rowData.beforeFirst();
thisRow = null;
}
}
/**
* JDBC 2.0 The cancelRowUpdates() method may be called after calling an
* updateXXX() method(s) and before calling updateRow() to rollback the
* updates made to a row. If no updates have been made or updateRow() has
* already been called, then this method has no effect.
*
* @exception SQLException if a database-access error occurs, or if called
* when on the insert row.
* @throws NotUpdatable DOCUMENT ME!
*/
public void cancelRowUpdates() throws SQLException {
throw new NotUpdatable();
}
/**
* After this call, getWarnings returns null until a new warning is
* reported for this ResultSet
*
* @exception java.sql.SQLException if a database access error occurs
*/
public void clearWarnings() throws java.sql.SQLException {
warningChain = null;
}
/**
* In some cases, it is desirable to immediately release a ResultSet
* database and JDBC resources instead of waiting for this to happen when
* it is automatically closed. The close method provides this immediate
* release.
*
* <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 java.sql.SQLException if a database access error occurs
*/
public void close() throws java.sql.SQLException {
realClose(true);
}
/**
* JDBC 2.0 Delete the current row from the result set and the underlying
* database. Cannot be called when on the insert row.
*
* @exception SQLException if a database-access error occurs, or if called
* when on the insert row.
* @throws NotUpdatable DOCUMENT ME!
*/
public void deleteRow() throws SQLException {
throw new NotUpdatable();
}
/**
* Map a ResultSet column name to a ResultSet column index
*
* @param columnName the name of the column
*
* @return the column index
*
* @exception java.sql.SQLException if a database access error occurs
*/
public int findColumn(String columnName) throws java.sql.SQLException {
Integer index;
synchronized (this) {
if (!hasBuiltIndexMapping) {
buildIndexMapping();
}
}
index = (Integer) columnNameToIndex.get(columnName);
if (index == null) {
index = (Integer) fullColumnNameToIndex.get(columnName);
}
if (index != null) {
return index.intValue() + 1;
} else {
// Try this inefficient way, now
String columnNameUC = columnName.toUpperCase();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName().toUpperCase().equals(columnNameUC)) {
return i + 1;
} else if (fields[i].getFullName().toUpperCase().equals(columnNameUC)) {
return i + 1;
}
}
throw new java.sql.SQLException("Column '" + columnName
+ "' not found.", SQLError.SQL_STATE_COLUMN_NOT_FOUND);
}
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "first", args);
}
checkClosed();
if (onInsertRow) {
onInsertRow = false;
}
if (rowData.isEmpty()) {
return false;
} else {
if (doingUpdates) {
doingUpdates = false;
}
rowData.beforeFirst();
thisRow = rowData.next();
return true;
}
}
/**
* JDBC 2.0 Insert the contents of the insert row into the result set and
* the database. Must be on the insert row when this method is called.
*
* @exception SQLException if a database-access error occurs, if called
* when not on the insert row, or if all non-nullable columns
* in the insert row have not been given a value
* @throws NotUpdatable DOCUMENT ME!
*/
public void insertRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0
*
* <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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "last", args);
}
checkClosed();
if (rowData.size() == 0) {
return false;
} else {
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
rowData.beforeLast();
thisRow = rowData.next();
return true;
}
}
/**
* JDBC 2.0 Move the cursor to the remembered cursor position, usually the
* current row. Has no effect unless the cursor is on the insert row.
*
* @exception SQLException if a database-access error occurs, or the result
* set is not updatable
* @throws NotUpdatable DOCUMENT ME!
*/
public void moveToCurrentRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Move to the insert row. The current cursor position is
* remembered while the cursor is positioned on the insert row. The insert
* row is a special row associated with an updatable result set. It is
* essentially a buffer where a new row may be constructed by calling the
* updateXXX() methods prior to inserting the row into the result set.
* Only the updateXXX(), getXXX(), and insertRow() methods may be called
* when the cursor is on the insert row. All of the columns in a result
* set must be given a value each time this method is called before
* calling insertRow(). UpdateXXX()must be called before getXXX() on a
* column.
*
* @exception SQLException if a database-access error occurs, or the result
* set is not updatable
* @throws NotUpdatable DOCUMENT ME!
*/
public void moveToInsertRow() throws SQLException {
throw new NotUpdatable();
}
/**
* A ResultSet is initially positioned before its first row, the first call
* to next makes the first row the current row; the second call makes the
* second row the current row, etc.
*
* <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 next() throws java.sql.SQLException {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "next", args);
}
checkClosed();
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
boolean b;
if (!reallyResult()) {
throw new java.sql.SQLException("ResultSet is from UPDATE. No Data",
SQLError.SQL_STATE_GENERAL_ERROR);
}
if (rowData.size() == 0) {
b = false;
} else {
if (!rowData.hasNext()) {
// force scroll past end
rowData.next();
b = false;
} else {
clearWarnings();
thisRow = rowData.next();
b = true;
}
}
if (Driver.TRACE) {
Debug.returnValue(this, "next", new Boolean(b));
}
return b;
}
/**
* The prev method is not part of JDBC, but because of the architecture of
* this driver it is possible to move both forward and backward within the
* result set.
*
* <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 {
checkClosed();
int rowIndex = rowData.getCurrentRowNumber();
if ((rowIndex - 1) >= 0) {
rowIndex--;
rowData.setCurrentRow(rowIndex);
thisRow = (byte[][]) rowData.getAt(rowIndex);
return true;
} else if ((rowIndex - 1) == -1) {
rowIndex--;
rowData.setCurrentRow(rowIndex);
thisRow = null;
return false;
} else {
return false;
}
}
/**
* 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 {
if (Driver.TRACE) {
Object[] args = { };
Debug.methodCall(this, "previous", args);
}
if (onInsertRow) {
onInsertRow = false;
}
if (doingUpdates) {
doingUpdates = false;
}
return prev();
}
/**
* JDBC 2.0 Refresh the value of the current row with its current value in
* the database. Cannot be called when on the insert row. The
* refreshRow() method provides a way for an application to explicitly
* tell the JDBC driver to refetch a row(s) from the database. An
* application may want to call refreshRow() when caching or prefetching
* is being done by the JDBC driver to fetch the latest value of a row
* from the database. The JDBC driver may actually refresh multiple rows
* at once if the fetch size is greater than one. All values are refetched
* subject to the transaction isolation level and cursor sensitivity. If
* refreshRow() is called after calling updateXXX(), but before calling
* updateRow() then the updates made to the row are lost. Calling
* refreshRow() frequently will likely slow performance.
*
* @exception SQLException if a database-access error occurs, or if called
* when on the insert row.
* @throws NotUpdatable DOCUMENT ME!
*/
public void refreshRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0
*
* <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 {
if (Driver.TRACE) {
Object[] args = { new Integer(rows) };
Debug.methodCall(this, "relative", args);
}
checkClosed();
if (rowData.size() == 0) {
return false;
}
rowData.moveRowRelative(rows);
thisRow = rowData.getAt(rowData.getCurrentRowNumber());
boolean b = (!rowData.isAfterLast() && !rowData.isBeforeFirst());
if (Driver.TRACE) {
Debug.returnValue(this, "relative", new Boolean(b));
}
return b;
}
/**
* JDBC 2.0 Determine if this row has been deleted. A deleted row may
* leave a visible "hole" in a result set. This method can be used to
* detect holes in a result set. The value returned depends on whether or
* not the result set can detect deletions.
*
* @return true if deleted and deletes are detected
*
* @exception SQLException if a database-access error occurs
* @throws NotImplemented DOCUMENT ME!
*
* @see DatabaseMetaData#deletesAreDetected
*/
public boolean rowDeleted() throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0 Determine if the current row has been inserted. The value
* returned depends on whether or not the result set can detect visible
* inserts.
*
* @return true if inserted and inserts are detected
*
* @exception SQLException if a database-access error occurs
* @throws NotImplemented DOCUMENT ME!
*
* @see DatabaseMetaData#insertsAreDetected
*/
public boolean rowInserted() throws SQLException {
throw new NotImplemented();
}
//---------------------------------------------------------------------
// Updates
//---------------------------------------------------------------------
/**
* JDBC 2.0 Determine if the current row has been updated. The value
* returned depends on whether or not the result set can detect updates.
*
* @return true if the row has been visibly updated by the owner or
* another, and updates are detected
*
* @exception SQLException if a database-access error occurs
* @throws NotImplemented DOCUMENT ME!
*
* @see DatabaseMetaData#updatesAreDetected
*/
public boolean rowUpdated() throws SQLException {
throw new NotImplemented();
}
/**
* @see ResultSet#updateArray(int, Array)
*/
public void updateArray(int arg0, Array arg1) throws SQLException {
throw new NotImplemented();
}
/**
* @see ResultSet#updateArray(String, Array)
*/
public void updateArray(String arg0, Array arg1) throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
* @param length the length of the stream
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateAsciiStream(int columnIndex, java.io.InputStream x,
int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName the name of the column
* @param x the new column value
* @param length of the stream
*
* @exception SQLException if a database-access error occurs
*/
public void updateAsciiStream(String columnName, java.io.InputStream x,
int length) throws SQLException {
updateAsciiStream(findColumn(columnName), x, length);
}
/**
* JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateBigDecimal(int columnIndex, BigDecimal x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a BigDecimal value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateBigDecimal(String columnName, BigDecimal x)
throws SQLException {
updateBigDecimal(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a binary stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
* @param length the length of the stream
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateBinaryStream(int columnIndex, java.io.InputStream x,
int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a binary stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName the name of the column
* @param x the new column value
* @param length of the stream
*
* @exception SQLException if a database-access error occurs
*/
public void updateBinaryStream(String columnName, java.io.InputStream x,
int length) throws SQLException {
updateBinaryStream(findColumn(columnName), x, length);
}
/**
* @see ResultSet#updateBlob(int, Blob)
*/
public void updateBlob(int arg0, java.sql.Blob arg1)
throws SQLException {
throw new NotUpdatable();
}
/**
* @see ResultSet#updateBlob(String, Blob)
*/
public void updateBlob(String arg0, java.sql.Blob arg1)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateBoolean(int columnIndex, boolean x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateBoolean(String columnName, boolean x)
throws SQLException {
updateBoolean(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateByte(int columnIndex, byte x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateByte(String columnName, byte x) throws SQLException {
updateByte(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a byte array value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateBytes(int columnIndex, byte[] x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a byte array value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateBytes(String columnName, byte[] x)
throws SQLException {
updateBytes(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a character stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
* @param length the length of the stream
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateCharacterStream(int columnIndex, java.io.Reader x,
int length) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a character stream value. The updateXXX()
* methods are used to update column values in the current row, or the
* insert row. The updateXXX() methods do not update the underlying
* database, instead the updateRow() or insertRow() methods are called to
* update the database.
*
* @param columnName the name of the column
* @param reader the stream to update the column with
* @param length of the stream
*
* @throws SQLException if a database-access error occurs
*/
public void updateCharacterStream(String columnName, java.io.Reader reader,
int length) throws SQLException {
updateCharacterStream(findColumn(columnName), reader, length);
}
/**
* @see ResultSet#updateClob(int, Clob)
*/
public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException {
throw new NotUpdatable();
}
/**
* @see ResultSet#updateClob(String, Clob)
*/
public void updateClob(String columnName, java.sql.Clob clob) throws SQLException {
updateClob(findColumn(columnName), clob);
}
/**
* JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateDate(int columnIndex, java.sql.Date x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateDate(String columnName, java.sql.Date x)
throws SQLException {
updateDate(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Double value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateDouble(int columnIndex, double x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a double value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateDouble(String columnName, double x)
throws SQLException {
updateDouble(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a float value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateFloat(int columnIndex, float x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a float value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateFloat(String columnName, float x)
throws SQLException {
updateFloat(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with an integer value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateInt(int columnIndex, int x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an integer value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateInt(String columnName, int x) throws SQLException {
updateInt(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a long value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateLong(int columnIndex, long x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a long value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateLong(String columnName, long x) throws SQLException {
updateLong(findColumn(columnName), x);
}
/**
* JDBC 2.0 Give a nullable column a null value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateNull(int columnIndex) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a null value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
*
* @exception SQLException if a database-access error occurs
*/
public void updateNull(String columnName) throws SQLException {
updateNull(findColumn(columnName));
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
* @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
* this is the number of digits after the decimal. For all other
* types this value will be ignored.
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateObject(int columnIndex, Object x, int scale)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateObject(int columnIndex, Object x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
* @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
* this is the number of digits after the decimal. For all other
* types this value will be ignored.
*
* @exception SQLException if a database-access error occurs
*/
public void updateObject(String columnName, Object x, int scale)
throws SQLException {
updateObject(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with an Object value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateObject(String columnName, Object x)
throws SQLException {
updateObject(findColumn(columnName), x);
}
/**
* @see ResultSet#updateRef(int, Ref)
*/
public void updateRef(int arg0, Ref arg1) throws SQLException {
throw new NotImplemented();
}
/**
* @see ResultSet#updateRef(String, Ref)
*/
public void updateRef(String arg0, Ref arg1) throws SQLException {
throw new NotImplemented();
}
/**
* JDBC 2.0 Update the underlying database with the new contents of the
* current row. Cannot be called when on the insert row.
*
* @exception SQLException if a database-access error occurs, or if called
* when on the insert row
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateRow() throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a short value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateShort(int columnIndex, short x) throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a short value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateShort(String columnName, short x)
throws SQLException {
updateShort(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a String value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateString(int columnIndex, String x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a String value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateString(String columnName, String x)
throws SQLException {
updateString(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateTime(int columnIndex, java.sql.Time x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
* used to update column values in the current row, or the insert row. The
* updateXXX() methods do not update the underlying database, instead the
* updateRow() or insertRow() methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateTime(String columnName, java.sql.Time x)
throws SQLException {
updateTime(findColumn(columnName), x);
}
/**
* JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
* @throws NotUpdatable DOCUMENT ME!
*/
public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
throws SQLException {
throw new NotUpdatable();
}
/**
* JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
* are used to update column values in the current row, or the insert row.
* The updateXXX() methods do not update the underlying database, instead
* the updateRow() or insertRow() methods are called to update the
* database.
*
* @param columnName the name of the column
* @param x the new column value
*
* @exception SQLException if a database-access error occurs
*/
public void updateTimestamp(String columnName, java.sql.Timestamp x)
throws SQLException {
updateTimestamp(findColumn(columnName), x);
}
/**
* A column may have the value of SQL NULL; wasNull() reports whether the
* last column read had this special value. Note that you must first call
* getXXX on a column to try to read its value and then call wasNull() to
* find if the value was SQL NULL
*
* @return true if the last column read was SQL NULL
*
* @exception java.sql.SQLException if a database access error occurred
*/
public boolean wasNull() throws java.sql.SQLException {
return wasNullFlag;
}
///////////////////////////////////////////
//
// These number conversion routines save
// a ton of "new()s", especially for the heavily
// used getInt() and getDouble() methods
//
///////////////////////////////////////////
/**
* Converts a string representation of a number to a double. Need a faster
* way to do this.
*
* @param colIndex the 1-based index of the column to retrieve a double
* from.
*
* @return the double value represented by the string in buf
*
* @throws SQLException if an error occurs
*/
protected double getDoubleInternal(int colIndex) throws SQLException {
String s = "";
try {
s = getString(colIndex);
if ((s == null) || (s.length() == 0)) {
return 0;
}
double d = Double.parseDouble(s);
if (this.useStrictFloatingPoint) {
// Fix endpoint rounding precision loss in MySQL server
if (d == 2.147483648E9) {
// Fix Odd end-point rounding on MySQL
d = 2.147483647E9;
} else if (d == 1.0000000036275E-15) {
// Fix odd end-point rounding on MySQL
d = 1.0E-15;
} else if (d == 9.999999869911E14) {
d = 9.99999999999999E14;
} else if (d == 1.4012984643248E-45) {
d = 1.4E-45;
} else if (d == 1.4013E-45) {
d = 1.4E-45;
} else if (d == 3.4028234663853E37) {
d = 3.4028235E37;
} else if (d == -2.14748E9) {
d = -2.147483648E9;
} else if (d == 3.40282E37) {
d = 3.4028235E37;
}
}
return d;
} catch (NumberFormatException e) {
throw new SQLException("Bad format for number '" + s + "'");
}
}
/**
* Sets the first character of the query that this result set was created
* from.
*
* @param c the first character of the query...uppercased
*/
protected void setFirstCharOfQuery(char c) {
this.firstCharOfQuery = c;
}
/**
* Returns the first character of the query that this result set was
* created from.
*
* @return the first character of the query...uppercased
*/
protected char getFirstCharOfQuery() {
return this.firstCharOfQuery;
}
/**
* Sets the concurrency (JDBC2)
*
* @param concurrencyFlag CONCUR_UPDATABLE or CONCUR_READONLY
*/
protected void setResultSetConcurrency(int concurrencyFlag) {
resultSetConcurrency = concurrencyFlag;
}
/**
* Sets the result set type for (JDBC2)
*
* @param typeFlag SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
* SCROLL_INSENSITIVE)
*/
protected void setResultSetType(int typeFlag) {
resultSetType = typeFlag;
}
/**
* Sets server info (if any)
*
* @param info the server info message
*/
protected void setServerInfo(String info) {
this.serverInfo = info;
}
/**
* Returns the server info (if any), or null if none.
*
* @return server info created for this ResultSet
*/
protected String getServerInfo() {
return this.serverInfo;
}
/**
* Builds a hash between column names and their indices for fast retrieval.
*/
protected void buildIndexMapping() {
int numFields = fields.length;
columnNameToIndex = new HashMap();
fullColumnNameToIndex = new HashMap();
// We do this in reverse order, so that the 'first' column
// with a given name ends up as the final mapping in the
// hashtable...
//
// Quoting the JDBC Spec:
//
// "Column names used as input to getter
// methods are case insensitive. When a getter method is called with a column
// name and several columns have the same name, the value of the first
// matching column will be returned. "
//
for (int i = numFields-1; i>= 0 ; i--) {
Integer index = new Integer(i);
String columnName = fields[i].getName();
String fullColumnName = fields[i].getFullName();
if (columnName != null) {
columnNameToIndex.put(columnName, index);
columnNameToIndex.put(columnName.toUpperCase(), index);
columnNameToIndex.put(columnName.toLowerCase(), index);
}
if (fullColumnName != null) {
fullColumnNameToIndex.put(fullColumnName, index);
fullColumnNameToIndex.put(fullColumnName.toUpperCase(), index);
fullColumnNameToIndex.put(fullColumnName.toLowerCase(), index);
}
}
// set the flag to prevent rebuilding...
hasBuiltIndexMapping = true;
}
/**
* Ensures that the result set is not closed
*
* @throws SQLException if the result set is closed
*/
protected void checkClosed() throws SQLException {
if (isClosed) {
throw new SQLException("Operation not allowed after ResultSet closed",
SQLError.SQL_STATE_GENERAL_ERROR);
}
}
/**
* Ensures that the cursor is positioned on a valid row and that the result
* set is not closed
*
* @throws SQLException if the result set is not in a valid state for
* traversal
*/
protected void checkRowPos() throws SQLException {
checkClosed();
if (!rowData.isDynamic() && (rowData.size() == 0)) {
throw new SQLException("Illegal operation on empty result set",
SQLError.SQL_STATE_GENERAL_ERROR);
}
if (rowData.isBeforeFirst()) {
throw new SQLException("Before start of result set", SQLError.SQL_STATE_GENERAL_ERROR);
}
if (rowData.isAfterLast()) {
throw new SQLException("After end of result set", SQLError.SQL_STATE_GENERAL_ERROR);
}
}
protected void realClose(boolean closeRowData) throws SQLException {
try {
if (closeRowData && (this.rowData != null)) {
rowData.close();
}
} finally {
rowData = null;
isClosed = true;
}
}
void setStatement(com.mysql.jdbc.Statement stmt) {
owningStatement = stmt;
}
long getUpdateCount() {
return updateCount;
}
long getUpdateID() {
return updateId;
}
boolean reallyResult() {
return reallyResult;
}
/**
* Get the value of a column in the current row as a java.sql.Time object
* in the given timezone
*
* @param columnIndex the first column is 1, the second is 2...
* @param tz the Timezone to use
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
*/
private Time getTimeInternal(int columnIndex, TimeZone tz)
throws java.sql.SQLException {
int hr = 0;
int min = 0;
int sec = 0;
try {
String timeAsString = getString(columnIndex);
if (timeAsString == null) {
return null;
} else {
int length = timeAsString.length();
if ((length > 0) && (timeAsString.charAt(0) == '0')
&& (timeAsString.equals("0000-00-00")
|| timeAsString.equals("0000-00-00 00:00:00")
|| timeAsString.equals("00000000000000"))) {
wasNullFlag = true;
return null;
}
Field timeColField = fields[columnIndex - 1];
if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
// It's a timestamp
switch (length) {
case 14:
case 12: {
hr = Integer.parseInt(timeAsString.substring(length - 6,
length - 4));
min = Integer.parseInt(timeAsString.substring(length
- 4, length - 2));
sec = Integer.parseInt(timeAsString.substring(length
- 2, length));
}
break;
case 10: {
hr = Integer.parseInt(timeAsString.substring(6, 8));
min = Integer.parseInt(timeAsString.substring(8, 10));
sec = 0;
}
break;
default:
throw new SQLException(
"Timestamp too small to convert to Time value in column "
+ columnIndex + "(" + fields[columnIndex - 1]
+ ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
} /* endswitch */
SQLWarning precisionLost = new SQLWarning(
"Precision lost converting TIMESTAMP to Time with getTime() on column "
+ columnIndex + "(" + fields[columnIndex - 1]
+ ").");
if (warningChain == null) {
warningChain = precisionLost;
} else {
warningChain.setNextWarning(precisionLost);
}
} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
hr = Integer.parseInt(timeAsString.substring(11, 13));
min = Integer.parseInt(timeAsString.substring(14, 16));
sec = Integer.parseInt(timeAsString.substring(17, 19));
SQLWarning precisionLost = new SQLWarning(
"Precision lost converting DATETIME to Time with getTime() on column "
+ columnIndex + "(" + fields[columnIndex - 1]
+ ").");
if (warningChain == null) {
warningChain = precisionLost;
} else {
warningChain.setNextWarning(precisionLost);
}
} else {
// convert a String to a Time
if ((length != 5) && (length != 8)) {
throw new SQLException("Bad format for Time '"
+ timeAsString + "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
hr = Integer.parseInt(timeAsString.substring(0, 2));
min = Integer.parseInt(timeAsString.substring(3, 5));
sec = (length == 5) ? 0
: Integer.parseInt(timeAsString
.substring(6));
}
return TimeUtil.changeTimezone(this.connection,
fastTimeCreate(null, hr, min, sec),
connection.getServerTimezone(), tz);
}
} catch (Exception ex) {
throw new java.sql.SQLException(ex.getClass().getName(), SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
/**
* Get the value of a column in the current row as a java.sql.Timestamp
* object in the given timezone
*
* @param columnIndex the first column is 1, the second is 2...
* @param tz the timezone to use
*
* @return the column value; null if SQL NULL
*
* @exception java.sql.SQLException if a database access error occurs
*/
private Timestamp getTimestampInternal(int columnIndex, TimeZone tz)
throws java.sql.SQLException {
String timestampValue = getString(columnIndex);
try {
if (timestampValue == null) {
return null;
} else {
int length = timestampValue.length();
if ((length > 0) && (timestampValue.charAt(0) == '0')
&& (timestampValue.equals("0000-00-00")
|| timestampValue.equals("0000-00-00 00:00:00")
|| timestampValue.equals("00000000000000")
|| timestampValue.equals("0"))) {
wasNullFlag = true;
return null;
} else if (fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null,
Integer.parseInt(timestampValue.substring(0, 4))
- 1900, 0, 1, 0, 0, 0, 0),
connection.getServerTimezone(), tz);
} else {
// Convert from TIMESTAMP or DATE
switch (length) {
case 19: {
int year = Integer.parseInt(timestampValue.substring(
0, 4));
int month = Integer.parseInt(timestampValue.substring(
5, 7));
int day = Integer.parseInt(timestampValue.substring(8,
10));
int hour = Integer.parseInt(timestampValue.substring(
11, 13));
int minutes = Integer.parseInt(timestampValue.substring(
14, 16));
int seconds = Integer.parseInt(timestampValue.substring(
17, 19));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year - 1900, month - 1,
day, hour, minutes, seconds, 0),
connection.getServerTimezone(), tz);
}
case 14: {
int year = Integer.parseInt(timestampValue.substring(
0, 4));
int month = Integer.parseInt(timestampValue.substring(
4, 6));
int day = Integer.parseInt(timestampValue.substring(6, 8));
int hour = Integer.parseInt(timestampValue.substring(
8, 10));
int minutes = Integer.parseInt(timestampValue.substring(
10, 12));
int seconds = Integer.parseInt(timestampValue.substring(
12, 14));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year - 1900, month - 1,
day, hour, minutes, seconds, 0),
connection.getServerTimezone(), tz);
}
case 12: {
int year = Integer.parseInt(timestampValue.substring(
0, 2));
if (year <= 69) {
year = (year + 100);
}
int month = Integer.parseInt(timestampValue.substring(
2, 4));
int day = Integer.parseInt(timestampValue.substring(4, 6));
int hour = Integer.parseInt(timestampValue.substring(
6, 8));
int minutes = Integer.parseInt(timestampValue.substring(
8, 10));
int seconds = Integer.parseInt(timestampValue.substring(
10, 12));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year, month - 1, day,
hour, minutes, seconds, 0),
connection.getServerTimezone(), tz);
}
case 10: {
int year;
int month;
int day;
int hour;
int minutes;
if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
|| (timestampValue.indexOf("-") != -1)) {
year = Integer.parseInt(timestampValue.substring(
0, 4)) - 1900;
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));
}
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year, month - 1, day,
hour, minutes, 0, 0),
connection.getServerTimezone(), tz);
}
case 8: {
int year = Integer.parseInt(timestampValue.substring(
0, 4));
int month = Integer.parseInt(timestampValue.substring(
4, 6));
int day = Integer.parseInt(timestampValue.substring(6, 8));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year - 1900, month - 1,
day, 0, 0, 0, 0),
connection.getServerTimezone(), tz);
}
case 6: {
int year = Integer.parseInt(timestampValue.substring(
0, 2));
if (year <= 69) {
year = (year + 100);
}
int month = Integer.parseInt(timestampValue.substring(
2, 4));
int day = Integer.parseInt(timestampValue.substring(4, 6));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year, month - 1, day, 0,
0, 0, 0), connection.getServerTimezone(), tz);
}
case 4: {
int year = Integer.parseInt(timestampValue.substring(
0, 2));
if (year <= 69) {
year = (year + 100);
}
int month = Integer.parseInt(timestampValue.substring(
2, 4));
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year, month - 1, 1, 0, 0,
0, 0), connection.getServerTimezone(), tz);
}
case 2: {
int year = Integer.parseInt(timestampValue.substring(
0, 2));
if (year <= 69) {
year = (year + 100);
}
return TimeUtil.changeTimezone(this.connection,
fastTimestampCreate(null, year, 0, 1, 0, 0, 0, 0),
connection.getServerTimezone(), tz);
}
default:
throw new java.sql.SQLException(
"Bad format for Timestamp '" + timestampValue
+ "' in column " + columnIndex + "("
+ fields[columnIndex - 1] + ").", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
}
} catch (Exception e) {
throw new java.sql.SQLException("Cannot convert value '"
+ timestampValue + "' from column " + columnIndex + "("
+ timestampValue + " ) to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
}
}
private synchronized Date fastDateCreate(Calendar cal, int year, int month,
int day) {
if (cal == null) {
if (this.fastDateCal == null) {
this.fastDateCal = new GregorianCalendar();
this.fastDateCal.setTimeZone(DEFAULT_TIMEZONE);
}
cal = this.fastDateCal;
}
cal.clear();
cal.set(year + 1900, month, day, 0, 0, 0);
long dateAsMillis = 0;
try {
dateAsMillis = cal.getTimeInMillis();
} catch (IllegalAccessError iae) {
// Must be on JDK-1.3.1 or older....
dateAsMillis = cal.getTime().getTime();
}
return new Date(dateAsMillis);
}
private synchronized Time fastTimeCreate(Calendar cal, int hour,
int minute, int second) {
if (cal == null) {
if (this.fastDateCal == null) {
this.fastDateCal = new GregorianCalendar();
this.fastDateCal.setTimeZone(DEFAULT_TIMEZONE);
}
cal = this.fastDateCal;
}
cal.clear();
// Set 'date' to epoch of Jan 1, 1970
cal.set(1970, 0, 1, hour, minute, second);
long timeAsMillis = 0;
try {
timeAsMillis = cal.getTimeInMillis();
} catch (IllegalAccessError iae) {
// Must be on JDK-1.3.1 or older....
timeAsMillis = cal.getTime().getTime();
}
return new Time(timeAsMillis);
}
private synchronized Timestamp fastTimestampCreate(Calendar cal, int year,
int month, int day, int hour, int minute, int seconds, int secondsPart) {
if (cal == null) {
if (this.fastDateCal == null) {
this.fastDateCal = new GregorianCalendar();
this.fastDateCal.setTimeZone(DEFAULT_TIMEZONE);
}
cal = this.fastDateCal;
}
cal.clear();
cal.set(year + 1900, month, day, hour, minute, seconds);
long tsAsMillis = 0;
try {
tsAsMillis = cal.getTimeInMillis();
} catch (IllegalAccessError iae) {
// Must be on JDK-1.3.1 or older....
tsAsMillis = cal.getTime().getTime();
}
Timestamp ts = new Timestamp(tsAsMillis);
ts.setNanos(secondsPart);
return ts;
}
}