List:Commits« Previous MessageNext Message »
From:mmatthews Date:June 15 2007 3:24am
Subject:Connector/J commit: r6451 - branches/branch_5_1/connector-j/src/com/mysql/jdbc
View as plain text  
Added:
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRow.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRow.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetRow.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataCursor.java
Removed:
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java
Modified:
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlIO.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetImpl.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowData.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataDynamic.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataKeyset.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataStatic.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java
   branches/branch_5_1/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java
Log:
Some renames around the Row(Holder) classes.

Row navigation now causes any streams/readers open on the result set
      to be closed, as in some cases we're reading directly from a shared network
      packet and it will be overwritten by the "next" row.

Copied: branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRow.java (from rev 6449, branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java)
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java	2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRow.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -0,0 +1,696 @@
+/*
+ Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ */
+package com.mysql.jdbc;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.sql.Date;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TimeZone;
+
+/**
+ * A RowHolder implementation that holds one row packet (which is re-used by the
+ * driver, and thus saves memory allocations), and tries when possible to avoid
+ * allocations to break out the results as individual byte[]s.
+ * 
+ * (this isn't possible when doing things like reading floating point values).
+ * 
+ * @version $Id: $
+ */
+public class BufferRow extends ResultSetRow {
+	private Buffer rowFromServer;
+
+	/**
+	 * The beginning of the row packet
+	 */
+	private int homePosition = 0;
+
+	/**
+	 * The last-requested index, used as an optimization, if you ask for the
+	 * same index, we won't seek to find it. If you ask for an index that is >
+	 * than the last one requested, we start seeking from the last requested
+	 * index.
+	 */
+	private int lastRequestedIndex = -1;
+
+	/**
+	 * The position of the last-requested index, optimization in concert with
+	 * lastRequestedIndex.
+	 */
+	private int lastRequestedPos;
+
+	/**
+	 * The metadata of the fields of this result set.
+	 */
+	private Field[] metadata;
+
+	/**
+	 * Is this a row from a server-side prepared statement? If so, they're
+	 * encoded differently, so we have different ways of finding where each
+	 * column is, and unpacking them.
+	 */
+	private boolean isBinaryEncoded;
+
+	/**
+	 * If binary-encoded, the NULL status of each column is at the beginning of
+	 * the row, so we
+	 */
+	private boolean[] isNull;
+
+	private List openStreams;
+
+	public BufferRow(Buffer buf, Field[] fields, boolean isBinaryEncoded)
+			throws SQLException {
+		this.rowFromServer = buf;
+		this.metadata = fields;
+		this.isBinaryEncoded = isBinaryEncoded;
+		this.homePosition = this.rowFromServer.getPosition();
+
+		if (fields != null) {
+			setMetadata(fields);
+		}
+	}
+
+	public synchronized void closeOpenStreams() {
+		if (this.openStreams != null) {
+			// This would've looked slicker in a "for" loop
+			// but we want to skip over streams that fail to
+			// close (they probably won't ever)
+			// to be more robust and close everything we _can_
+
+			Iterator iter = this.openStreams.iterator();
+
+			while (iter.hasNext()) {
+
+				try {
+					((InputStream) iter.next()).close();
+				} catch (IOException e) {
+					// ignore - it can't really happen in this case
+				}
+			}
+
+			this.openStreams.clear();
+		}
+	}
+
+	private int findAndSeekToOffset(int index) throws SQLException {
+		if (!this.isBinaryEncoded) {
+
+			if (index == 0) {
+				this.lastRequestedIndex = 0;
+				this.lastRequestedPos = this.homePosition;
+				this.rowFromServer.setPosition(this.homePosition);
+
+				return 0;
+			}
+
+			if (index == this.lastRequestedIndex) {
+				this.rowFromServer.setPosition(this.lastRequestedPos);
+
+				return this.lastRequestedPos;
+			}
+
+			int startingIndex = 0;
+
+			if (index > this.lastRequestedIndex) {
+				startingIndex = this.lastRequestedIndex;
+				this.rowFromServer.setPosition(this.lastRequestedPos);
+			} else {
+				this.rowFromServer.setPosition(this.homePosition);
+			}
+
+			for (int i = startingIndex; i < index; i++) {
+				this.rowFromServer.fastSkipLenByteArray();
+			}
+
+			this.lastRequestedIndex = index;
+			this.lastRequestedPos = this.rowFromServer.getPosition();
+
+			return this.lastRequestedPos;
+		}
+
+		return findAndSeekToOffsetForBinaryEncoding(index);
+	}
+
+	private int findAndSeekToOffsetForBinaryEncoding(int index)
+			throws SQLException {
+		if (index == 0) {
+			this.lastRequestedIndex = 0;
+			this.lastRequestedPos = this.homePosition;
+
+			return 0;
+		}
+
+		if (index == this.lastRequestedIndex) {
+			this.rowFromServer.setPosition(this.lastRequestedPos);
+
+			return this.lastRequestedPos;
+		}
+
+		int startingIndex = 0;
+
+		if (index > this.lastRequestedIndex) {
+			startingIndex = this.lastRequestedIndex;
+			this.rowFromServer.setPosition(this.lastRequestedPos);
+		} else {
+			this.rowFromServer.setPosition(this.homePosition);
+		}
+
+		for (int i = startingIndex; i < index; i++) {
+			if (this.isNull[i]) {
+				continue;
+			}
+
+			int curPosition = this.rowFromServer.getPosition();
+
+			switch (this.metadata[i].getMysqlType()) {
+			case MysqlDefs.FIELD_TYPE_NULL:
+				break; // for dummy binds
+
+			case MysqlDefs.FIELD_TYPE_TINY:
+
+				this.rowFromServer.setPosition(curPosition + 1);
+				break;
+
+			case MysqlDefs.FIELD_TYPE_SHORT:
+			case MysqlDefs.FIELD_TYPE_YEAR:
+				this.rowFromServer.setPosition(curPosition + 2);
+
+				break;
+			case MysqlDefs.FIELD_TYPE_LONG:
+			case MysqlDefs.FIELD_TYPE_INT24:
+				this.rowFromServer.setPosition(curPosition + 4);
+
+				break;
+			case MysqlDefs.FIELD_TYPE_LONGLONG:
+				this.rowFromServer.setPosition(curPosition + 8);
+
+				break;
+			case MysqlDefs.FIELD_TYPE_FLOAT:
+				this.rowFromServer.setPosition(curPosition + 4);
+
+				break;
+			case MysqlDefs.FIELD_TYPE_DOUBLE:
+				this.rowFromServer.setPosition(curPosition + 8);
+
+				break;
+			case MysqlDefs.FIELD_TYPE_TIME:
+				this.rowFromServer.fastSkipLenByteArray();
+
+				break;
+			case MysqlDefs.FIELD_TYPE_DATE:
+
+				this.rowFromServer.fastSkipLenByteArray();
+
+				break;
+			case MysqlDefs.FIELD_TYPE_DATETIME:
+			case MysqlDefs.FIELD_TYPE_TIMESTAMP:
+				this.rowFromServer.fastSkipLenByteArray();
+
+				break;
+			case MysqlDefs.FIELD_TYPE_TINY_BLOB:
+			case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
+			case MysqlDefs.FIELD_TYPE_LONG_BLOB:
+			case MysqlDefs.FIELD_TYPE_BLOB:
+			case MysqlDefs.FIELD_TYPE_VAR_STRING:
+			case MysqlDefs.FIELD_TYPE_VARCHAR:
+			case MysqlDefs.FIELD_TYPE_STRING:
+			case MysqlDefs.FIELD_TYPE_DECIMAL:
+			case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
+			case MysqlDefs.FIELD_TYPE_GEOMETRY:
+			case MysqlDefs.FIELD_TYPE_BIT:
+				this.rowFromServer.fastSkipLenByteArray();
+
+				break;
+
+			default:
+				throw SQLError.createSQLException(Messages
+						.getString("MysqlIO.97") //$NON-NLS-1$
+						+ this.metadata[i].getMysqlType()
+						+ Messages.getString("MysqlIO.98")
+						+ (i + 1)
+						+ Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$
+						+ this.metadata.length
+						+ Messages.getString("MysqlIO.100"), //$NON-NLS-1$
+						SQLError.SQL_STATE_GENERAL_ERROR);
+			}
+		}
+
+		this.lastRequestedIndex = index;
+		this.lastRequestedPos = this.rowFromServer.getPosition();
+
+		return this.lastRequestedPos;
+	}
+
+	public synchronized InputStream getBinaryInputStream(int columnIndex)
+			throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		InputStream stream = new ByteArrayInputStream(this.rowFromServer
+				.getByteBuffer(), offset, (int) length);
+
+		if (this.openStreams == null) {
+			this.openStreams = new LinkedList();
+		}
+
+		return stream;
+	}
+
+	public byte[] getColumnValue(int index) throws SQLException {
+		findAndSeekToOffset(index);
+
+		if (!this.isBinaryEncoded) {
+			return this.rowFromServer.readLenByteArray(0);
+		}
+
+		if (this.isNull[index]) {
+			return null;
+		}
+
+		switch (this.metadata[index].getMysqlType()) {
+		case MysqlDefs.FIELD_TYPE_NULL:
+			return null;
+
+		case MysqlDefs.FIELD_TYPE_TINY:
+			return new byte[] { this.rowFromServer.readByte() };
+
+		case MysqlDefs.FIELD_TYPE_SHORT:
+		case MysqlDefs.FIELD_TYPE_YEAR:
+			return this.rowFromServer.getBytes(2);
+
+		case MysqlDefs.FIELD_TYPE_LONG:
+		case MysqlDefs.FIELD_TYPE_INT24:
+			return this.rowFromServer.getBytes(4);
+
+		case MysqlDefs.FIELD_TYPE_LONGLONG:
+			return this.rowFromServer.getBytes(8);
+
+		case MysqlDefs.FIELD_TYPE_FLOAT:
+			return this.rowFromServer.getBytes(4);
+
+		case MysqlDefs.FIELD_TYPE_DOUBLE:
+			return this.rowFromServer.getBytes(8);
+
+		case MysqlDefs.FIELD_TYPE_TIME:
+		case MysqlDefs.FIELD_TYPE_DATE:
+		case MysqlDefs.FIELD_TYPE_DATETIME:
+		case MysqlDefs.FIELD_TYPE_TIMESTAMP:
+		case MysqlDefs.FIELD_TYPE_TINY_BLOB:
+		case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
+		case MysqlDefs.FIELD_TYPE_LONG_BLOB:
+		case MysqlDefs.FIELD_TYPE_BLOB:
+		case MysqlDefs.FIELD_TYPE_VAR_STRING:
+		case MysqlDefs.FIELD_TYPE_VARCHAR:
+		case MysqlDefs.FIELD_TYPE_STRING:
+		case MysqlDefs.FIELD_TYPE_DECIMAL:
+		case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
+		case MysqlDefs.FIELD_TYPE_GEOMETRY:
+		case MysqlDefs.FIELD_TYPE_BIT:
+			return this.rowFromServer.readLenByteArray(0);
+
+		default:
+			throw SQLError.createSQLException(Messages.getString("MysqlIO.97") //$NON-NLS-1$
+					+ this.metadata[index].getMysqlType()
+					+ Messages.getString("MysqlIO.98")
+					+ (index + 1)
+					+ Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$
+					+ this.metadata.length + Messages.getString("MysqlIO.100"), //$NON-NLS-1$
+					SQLError.SQL_STATE_GENERAL_ERROR);
+		}
+	}
+
+	public int getInt(int columnIndex) throws SQLException {
+
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return StringUtils.getInt(this.rowFromServer.getByteBuffer(), offset,
+				offset + (int) length);
+	}
+
+	public long getLong(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return StringUtils.getLong(this.rowFromServer.getByteBuffer(), offset,
+				offset + (int) length);
+	}
+
+	public double getNativeDouble(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return getNativeDouble(this.rowFromServer.getByteBuffer(), offset);
+	}
+
+	public float getNativeFloat(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return getNativeFloat(this.rowFromServer.getByteBuffer(), offset);
+	}
+
+	public int getNativeInt(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return getNativeInt(this.rowFromServer.getByteBuffer(), offset);
+	}
+
+	public long getNativeLong(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return getNativeLong(this.rowFromServer.getByteBuffer(), offset);
+	}
+
+	public short getNativeShort(int columnIndex) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return getNativeShort(this.rowFromServer.getByteBuffer(), offset);
+	}
+
+	public Timestamp getNativeTimestamp(int columnIndex,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		return getNativeTimestamp(this.rowFromServer.getByteBuffer(), offset,
+				(int) length, targetCalendar, tz, rollForward, conn, rs);
+	}
+
+	public Reader getReader(int columnIndex) throws SQLException {
+		InputStream stream = getBinaryInputStream(columnIndex);
+
+		if (stream == null) {
+			return null;
+		}
+
+		try {
+			return new InputStreamReader(stream, this.metadata[columnIndex]
+					.getCharacterSet());
+		} catch (UnsupportedEncodingException e) {
+			SQLException sqlEx = SQLError.createSQLException("");
+
+			sqlEx.initCause(e);
+
+			throw sqlEx;
+		}
+	}
+
+	public String getString(int index, String encoding, ConnectionImpl conn)
+			throws SQLException {
+		findAndSeekToOffset(index);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		if (length == 0) {
+			return "";
+		}
+
+		// TODO: I don't like this, would like to push functionality back
+		// to the buffer class somehow
+
+		int offset = this.rowFromServer.getPosition();
+
+		return getString(encoding, conn, this.rowFromServer.getByteBuffer(),
+				offset, (int) length);
+	}
+
+	public Time getTimeFast(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		if (isNull(columnIndex)) {
+			return null;
+		}
+
+		int offset = findAndSeekToOffset(columnIndex);
+
+		int length = (int) this.rowFromServer.readFieldLength();
+
+		return getTimeFast(columnIndex, this.rowFromServer.getByteBuffer(),
+				offset, length, targetCalendar, tz, rollForward, conn, rs);
+	}
+
+	public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		if (isNull(columnIndex)) {
+			return null;
+		}
+
+		int offset = findAndSeekToOffset(columnIndex);
+
+		int length = (int) this.rowFromServer.readFieldLength();
+
+		return getTimestampFast(columnIndex,
+				this.rowFromServer.getByteBuffer(), offset, length, targetCalendar, tz,
+				rollForward, conn, rs);
+	}
+
+	public boolean isFloatingPointNumber(int index) throws SQLException {
+		if (this.isBinaryEncoded) {
+			switch (this.metadata[index].getSQLType()) {
+			case Types.FLOAT:
+			case Types.DOUBLE:
+			case Types.DECIMAL:
+			case Types.NUMERIC:
+				return true;
+			default:
+				return false;
+			}
+		}
+
+		findAndSeekToOffset(index);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return false;
+		}
+
+		if (length == 0) {
+			return false;
+		}
+
+		for (int i = 0; i < (int) length; i++) {
+			char c = (char) this.rowFromServer.readByte();
+
+			if ((c == 'e') || (c == 'E')) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	public boolean isNull(int index) throws SQLException {
+		if (!this.isBinaryEncoded) {
+			findAndSeekToOffset(index);
+
+			return this.rowFromServer.readFieldLength() == Buffer.NULL_LENGTH;
+		}
+
+		return this.isNull[index];
+	}
+
+	public long length(int index) throws SQLException {
+		findAndSeekToOffset(index);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return 0;
+		}
+
+		return length;
+	}
+
+	public void setColumnValue(int index, byte[] value) throws SQLException {
+		throw new OperationNotSupportedException();
+	}
+
+	public void setMetadata(Field[] f) throws SQLException {
+		super.setMetadata(f);
+
+		if (this.isBinaryEncoded) {
+			setupIsNullBitmask();
+		}
+	}
+
+	/**
+	 * Unpacks the bitmask at the head of the row packet that tells us what
+	 * columns hold null values, and sets the "home" position directly after the
+	 * bitmask.
+	 */
+	private void setupIsNullBitmask() throws SQLException {
+		int nullCount = (this.metadata.length + 9) / 8;
+
+		byte[] nullBitMask = new byte[nullCount];
+
+		for (int i = 0; i < nullCount; i++) {
+			nullBitMask[i] = this.rowFromServer.readByte();
+		}
+
+		this.homePosition = this.rowFromServer.getPosition();
+
+		this.isNull = new boolean[this.metadata.length];
+
+		int nullMaskPos = 0;
+		int bit = 4; // first two bits are reserved for future use
+
+		for (int i = 0; i < this.metadata.length; i++) {
+
+			this.isNull[i] = ((nullBitMask[nullMaskPos] & bit) != 0);
+
+			if (((bit <<= 1) & 255) == 0) {
+				bit = 1; /* To next byte */
+
+				nullMaskPos++;
+			}
+		}
+	}
+
+	public Date getDateFast(int columnIndex, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		if (isNull(columnIndex)) {
+			return null;
+		}
+
+		int offset = findAndSeekToOffset(columnIndex);
+
+		int length = (int) this.rowFromServer.readFieldLength();
+
+		return getDateFast(columnIndex, this.rowFromServer.getByteBuffer(),
+				offset, length, conn, rs);
+	}
+
+	public java.sql.Date getNativeDate(int columnIndex, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		return getNativeDate(columnIndex, this.rowFromServer.getByteBuffer(),
+				offset, (int) length, conn, rs);
+	}
+
+	public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar,
+			int jdbcType, int mysqlType, TimeZone tz,
+			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		return getNativeDateTimeValue(columnIndex, this.rowFromServer
+				.getByteBuffer(), offset, (int) length, targetCalendar, jdbcType,
+				mysqlType, tz, rollForward, conn, rs);
+	}
+
+	public Time getNativeTime(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		int offset = findAndSeekToOffset(columnIndex);
+
+		long length = this.rowFromServer.readFieldLength();
+
+		if (length == Buffer.NULL_LENGTH) {
+			return null;
+		}
+
+		return getNativeTime(columnIndex, this.rowFromServer.getByteBuffer(),
+				offset, (int) length, targetCalendar, tz, rollForward, conn, rs);
+	}
+}
\ No newline at end of file

Deleted: branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/BufferRowHolder.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1,696 +0,0 @@
-/*
- Copyright (C) 2007 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as 
- published by the Free Software Foundation.
-
- There are special exceptions to the terms and conditions of the GPL 
- as it is applied to this software. View the full text of the 
- exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
- software distribution.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- 
- */
-package com.mysql.jdbc;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.sql.Date;
-import java.sql.SQLException;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.sql.Types;
-import java.util.Calendar;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.TimeZone;
-
-/**
- * A RowHolder implementation that holds one row packet (which is re-used by the
- * driver, and thus saves memory allocations), and tries when possible to avoid
- * allocations to break out the results as individual byte[]s.
- * 
- * (this isn't possible when doing things like reading floating point values).
- * 
- * @version $Id: $
- */
-public class BufferRowHolder extends RowHolder {
-	private Buffer rowFromServer;
-
-	/**
-	 * The beginning of the row packet
-	 */
-	private int homePosition = 0;
-
-	/**
-	 * The last-requested index, used as an optimization, if you ask for the
-	 * same index, we won't seek to find it. If you ask for an index that is >
-	 * than the last one requested, we start seeking from the last requested
-	 * index.
-	 */
-	private int lastRequestedIndex = -1;
-
-	/**
-	 * The position of the last-requested index, optimization in concert with
-	 * lastRequestedIndex.
-	 */
-	private int lastRequestedPos;
-
-	/**
-	 * The metadata of the fields of this result set.
-	 */
-	private Field[] metadata;
-
-	/**
-	 * Is this a row from a server-side prepared statement? If so, they're
-	 * encoded differently, so we have different ways of finding where each
-	 * column is, and unpacking them.
-	 */
-	private boolean isBinaryEncoded;
-
-	/**
-	 * If binary-encoded, the NULL status of each column is at the beginning of
-	 * the row, so we
-	 */
-	private boolean[] isNull;
-
-	private List openStreams;
-
-	public BufferRowHolder(Buffer buf, Field[] fields, boolean isBinaryEncoded)
-			throws SQLException {
-		this.rowFromServer = buf;
-		this.metadata = fields;
-		this.isBinaryEncoded = isBinaryEncoded;
-		this.homePosition = this.rowFromServer.getPosition();
-
-		if (fields != null) {
-			setMetadata(fields);
-		}
-	}
-
-	public synchronized void closeOpenStreams() {
-		if (this.openStreams != null) {
-			// This would've looked slicker in a "for" loop
-			// but we want to skip over streams that fail to
-			// close (they probably won't ever)
-			// to be more robust and close everything we _can_
-
-			Iterator iter = this.openStreams.iterator();
-
-			while (iter.hasNext()) {
-
-				try {
-					((InputStream) iter.next()).close();
-				} catch (IOException e) {
-					// ignore - it can't really happen in this case
-				}
-			}
-
-			this.openStreams.clear();
-		}
-	}
-
-	private int findAndSeekToOffset(int index) throws SQLException {
-		if (!this.isBinaryEncoded) {
-
-			if (index == 0) {
-				this.lastRequestedIndex = 0;
-				this.lastRequestedPos = this.homePosition;
-				this.rowFromServer.setPosition(this.homePosition);
-
-				return 0;
-			}
-
-			if (index == this.lastRequestedIndex) {
-				this.rowFromServer.setPosition(this.lastRequestedPos);
-
-				return this.lastRequestedPos;
-			}
-
-			int startingIndex = 0;
-
-			if (index > this.lastRequestedIndex) {
-				startingIndex = this.lastRequestedIndex;
-				this.rowFromServer.setPosition(this.lastRequestedPos);
-			} else {
-				this.rowFromServer.setPosition(this.homePosition);
-			}
-
-			for (int i = startingIndex; i < index; i++) {
-				this.rowFromServer.fastSkipLenByteArray();
-			}
-
-			this.lastRequestedIndex = index;
-			this.lastRequestedPos = this.rowFromServer.getPosition();
-
-			return this.lastRequestedPos;
-		}
-
-		return findAndSeekToOffsetForBinaryEncoding(index);
-	}
-
-	private int findAndSeekToOffsetForBinaryEncoding(int index)
-			throws SQLException {
-		if (index == 0) {
-			this.lastRequestedIndex = 0;
-			this.lastRequestedPos = this.homePosition;
-
-			return 0;
-		}
-
-		if (index == this.lastRequestedIndex) {
-			this.rowFromServer.setPosition(this.lastRequestedPos);
-
-			return this.lastRequestedPos;
-		}
-
-		int startingIndex = 0;
-
-		if (index > this.lastRequestedIndex) {
-			startingIndex = this.lastRequestedIndex;
-			this.rowFromServer.setPosition(this.lastRequestedPos);
-		} else {
-			this.rowFromServer.setPosition(this.homePosition);
-		}
-
-		for (int i = startingIndex; i < index; i++) {
-			if (this.isNull[i]) {
-				continue;
-			}
-
-			int curPosition = this.rowFromServer.getPosition();
-
-			switch (this.metadata[i].getMysqlType()) {
-			case MysqlDefs.FIELD_TYPE_NULL:
-				break; // for dummy binds
-
-			case MysqlDefs.FIELD_TYPE_TINY:
-
-				this.rowFromServer.setPosition(curPosition + 1);
-				break;
-
-			case MysqlDefs.FIELD_TYPE_SHORT:
-			case MysqlDefs.FIELD_TYPE_YEAR:
-				this.rowFromServer.setPosition(curPosition + 2);
-
-				break;
-			case MysqlDefs.FIELD_TYPE_LONG:
-			case MysqlDefs.FIELD_TYPE_INT24:
-				this.rowFromServer.setPosition(curPosition + 4);
-
-				break;
-			case MysqlDefs.FIELD_TYPE_LONGLONG:
-				this.rowFromServer.setPosition(curPosition + 8);
-
-				break;
-			case MysqlDefs.FIELD_TYPE_FLOAT:
-				this.rowFromServer.setPosition(curPosition + 4);
-
-				break;
-			case MysqlDefs.FIELD_TYPE_DOUBLE:
-				this.rowFromServer.setPosition(curPosition + 8);
-
-				break;
-			case MysqlDefs.FIELD_TYPE_TIME:
-				this.rowFromServer.fastSkipLenByteArray();
-
-				break;
-			case MysqlDefs.FIELD_TYPE_DATE:
-
-				this.rowFromServer.fastSkipLenByteArray();
-
-				break;
-			case MysqlDefs.FIELD_TYPE_DATETIME:
-			case MysqlDefs.FIELD_TYPE_TIMESTAMP:
-				this.rowFromServer.fastSkipLenByteArray();
-
-				break;
-			case MysqlDefs.FIELD_TYPE_TINY_BLOB:
-			case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
-			case MysqlDefs.FIELD_TYPE_LONG_BLOB:
-			case MysqlDefs.FIELD_TYPE_BLOB:
-			case MysqlDefs.FIELD_TYPE_VAR_STRING:
-			case MysqlDefs.FIELD_TYPE_VARCHAR:
-			case MysqlDefs.FIELD_TYPE_STRING:
-			case MysqlDefs.FIELD_TYPE_DECIMAL:
-			case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
-			case MysqlDefs.FIELD_TYPE_GEOMETRY:
-			case MysqlDefs.FIELD_TYPE_BIT:
-				this.rowFromServer.fastSkipLenByteArray();
-
-				break;
-
-			default:
-				throw SQLError.createSQLException(Messages
-						.getString("MysqlIO.97") //$NON-NLS-1$
-						+ this.metadata[i].getMysqlType()
-						+ Messages.getString("MysqlIO.98")
-						+ (i + 1)
-						+ Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$
-						+ this.metadata.length
-						+ Messages.getString("MysqlIO.100"), //$NON-NLS-1$
-						SQLError.SQL_STATE_GENERAL_ERROR);
-			}
-		}
-
-		this.lastRequestedIndex = index;
-		this.lastRequestedPos = this.rowFromServer.getPosition();
-
-		return this.lastRequestedPos;
-	}
-
-	public synchronized InputStream getBinaryInputStream(int columnIndex)
-			throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		InputStream stream = new ByteArrayInputStream(this.rowFromServer
-				.getByteBuffer(), offset, (int) length);
-
-		if (this.openStreams == null) {
-			this.openStreams = new LinkedList();
-		}
-
-		return stream;
-	}
-
-	public byte[] getColumnValue(int index) throws SQLException {
-		findAndSeekToOffset(index);
-
-		if (!this.isBinaryEncoded) {
-			return this.rowFromServer.readLenByteArray(0);
-		}
-
-		if (this.isNull[index]) {
-			return null;
-		}
-
-		switch (this.metadata[index].getMysqlType()) {
-		case MysqlDefs.FIELD_TYPE_NULL:
-			return null;
-
-		case MysqlDefs.FIELD_TYPE_TINY:
-			return new byte[] { this.rowFromServer.readByte() };
-
-		case MysqlDefs.FIELD_TYPE_SHORT:
-		case MysqlDefs.FIELD_TYPE_YEAR:
-			return this.rowFromServer.getBytes(2);
-
-		case MysqlDefs.FIELD_TYPE_LONG:
-		case MysqlDefs.FIELD_TYPE_INT24:
-			return this.rowFromServer.getBytes(4);
-
-		case MysqlDefs.FIELD_TYPE_LONGLONG:
-			return this.rowFromServer.getBytes(8);
-
-		case MysqlDefs.FIELD_TYPE_FLOAT:
-			return this.rowFromServer.getBytes(4);
-
-		case MysqlDefs.FIELD_TYPE_DOUBLE:
-			return this.rowFromServer.getBytes(8);
-
-		case MysqlDefs.FIELD_TYPE_TIME:
-		case MysqlDefs.FIELD_TYPE_DATE:
-		case MysqlDefs.FIELD_TYPE_DATETIME:
-		case MysqlDefs.FIELD_TYPE_TIMESTAMP:
-		case MysqlDefs.FIELD_TYPE_TINY_BLOB:
-		case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
-		case MysqlDefs.FIELD_TYPE_LONG_BLOB:
-		case MysqlDefs.FIELD_TYPE_BLOB:
-		case MysqlDefs.FIELD_TYPE_VAR_STRING:
-		case MysqlDefs.FIELD_TYPE_VARCHAR:
-		case MysqlDefs.FIELD_TYPE_STRING:
-		case MysqlDefs.FIELD_TYPE_DECIMAL:
-		case MysqlDefs.FIELD_TYPE_NEW_DECIMAL:
-		case MysqlDefs.FIELD_TYPE_GEOMETRY:
-		case MysqlDefs.FIELD_TYPE_BIT:
-			return this.rowFromServer.readLenByteArray(0);
-
-		default:
-			throw SQLError.createSQLException(Messages.getString("MysqlIO.97") //$NON-NLS-1$
-					+ this.metadata[index].getMysqlType()
-					+ Messages.getString("MysqlIO.98")
-					+ (index + 1)
-					+ Messages.getString("MysqlIO.99") //$NON-NLS-1$ //$NON-NLS-2$
-					+ this.metadata.length + Messages.getString("MysqlIO.100"), //$NON-NLS-1$
-					SQLError.SQL_STATE_GENERAL_ERROR);
-		}
-	}
-
-	public int getInt(int columnIndex) throws SQLException {
-
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return StringUtils.getInt(this.rowFromServer.getByteBuffer(), offset,
-				offset + (int) length);
-	}
-
-	public long getLong(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return StringUtils.getLong(this.rowFromServer.getByteBuffer(), offset,
-				offset + (int) length);
-	}
-
-	public double getNativeDouble(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return getNativeDouble(this.rowFromServer.getByteBuffer(), offset);
-	}
-
-	public float getNativeFloat(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return getNativeFloat(this.rowFromServer.getByteBuffer(), offset);
-	}
-
-	public int getNativeInt(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return getNativeInt(this.rowFromServer.getByteBuffer(), offset);
-	}
-
-	public long getNativeLong(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return getNativeLong(this.rowFromServer.getByteBuffer(), offset);
-	}
-
-	public short getNativeShort(int columnIndex) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return getNativeShort(this.rowFromServer.getByteBuffer(), offset);
-	}
-
-	public Timestamp getNativeTimestamp(int columnIndex,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		return getNativeTimestamp(this.rowFromServer.getByteBuffer(), offset,
-				(int) length, targetCalendar, tz, rollForward, conn, rs);
-	}
-
-	public Reader getReader(int columnIndex) throws SQLException {
-		InputStream stream = getBinaryInputStream(columnIndex);
-
-		if (stream == null) {
-			return null;
-		}
-
-		try {
-			return new InputStreamReader(stream, this.metadata[columnIndex]
-					.getCharacterSet());
-		} catch (UnsupportedEncodingException e) {
-			SQLException sqlEx = SQLError.createSQLException("");
-
-			sqlEx.initCause(e);
-
-			throw sqlEx;
-		}
-	}
-
-	public String getString(int index, String encoding, ConnectionImpl conn)
-			throws SQLException {
-		findAndSeekToOffset(index);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		if (length == 0) {
-			return "";
-		}
-
-		// TODO: I don't like this, would like to push functionality back
-		// to the buffer class somehow
-
-		int offset = this.rowFromServer.getPosition();
-
-		return getString(encoding, conn, this.rowFromServer.getByteBuffer(),
-				offset, (int) length);
-	}
-
-	public Time getTimeFast(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		if (isNull(columnIndex)) {
-			return null;
-		}
-
-		int offset = findAndSeekToOffset(columnIndex);
-
-		int length = (int) this.rowFromServer.readFieldLength();
-
-		return getTimeFast(columnIndex, this.rowFromServer.getByteBuffer(),
-				offset, length, targetCalendar, tz, rollForward, conn, rs);
-	}
-
-	public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		if (isNull(columnIndex)) {
-			return null;
-		}
-
-		int offset = findAndSeekToOffset(columnIndex);
-
-		int length = (int) this.rowFromServer.readFieldLength();
-
-		return getTimestampFast(columnIndex,
-				this.rowFromServer.getByteBuffer(), offset, length, targetCalendar, tz,
-				rollForward, conn, rs);
-	}
-
-	public boolean isFloatingPointNumber(int index) throws SQLException {
-		if (this.isBinaryEncoded) {
-			switch (this.metadata[index].getSQLType()) {
-			case Types.FLOAT:
-			case Types.DOUBLE:
-			case Types.DECIMAL:
-			case Types.NUMERIC:
-				return true;
-			default:
-				return false;
-			}
-		}
-
-		findAndSeekToOffset(index);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return false;
-		}
-
-		if (length == 0) {
-			return false;
-		}
-
-		for (int i = 0; i < (int) length; i++) {
-			char c = (char) this.rowFromServer.readByte();
-
-			if ((c == 'e') || (c == 'E')) {
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	public boolean isNull(int index) throws SQLException {
-		if (!this.isBinaryEncoded) {
-			findAndSeekToOffset(index);
-
-			return this.rowFromServer.readFieldLength() == Buffer.NULL_LENGTH;
-		}
-
-		return this.isNull[index];
-	}
-
-	public long length(int index) throws SQLException {
-		findAndSeekToOffset(index);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return 0;
-		}
-
-		return length;
-	}
-
-	public void setColumnValue(int index, byte[] value) throws SQLException {
-		throw new OperationNotSupportedException();
-	}
-
-	public void setMetadata(Field[] f) throws SQLException {
-		super.setMetadata(f);
-
-		if (this.isBinaryEncoded) {
-			setupIsNullBitmask();
-		}
-	}
-
-	/**
-	 * Unpacks the bitmask at the head of the row packet that tells us what
-	 * columns hold null values, and sets the "home" position directly after the
-	 * bitmask.
-	 */
-	private void setupIsNullBitmask() throws SQLException {
-		int nullCount = (this.metadata.length + 9) / 8;
-
-		byte[] nullBitMask = new byte[nullCount];
-
-		for (int i = 0; i < nullCount; i++) {
-			nullBitMask[i] = this.rowFromServer.readByte();
-		}
-
-		this.homePosition = this.rowFromServer.getPosition();
-
-		this.isNull = new boolean[this.metadata.length];
-
-		int nullMaskPos = 0;
-		int bit = 4; // first two bits are reserved for future use
-
-		for (int i = 0; i < this.metadata.length; i++) {
-
-			this.isNull[i] = ((nullBitMask[nullMaskPos] & bit) != 0);
-
-			if (((bit <<= 1) & 255) == 0) {
-				bit = 1; /* To next byte */
-
-				nullMaskPos++;
-			}
-		}
-	}
-
-	public Date getDateFast(int columnIndex, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		if (isNull(columnIndex)) {
-			return null;
-		}
-
-		int offset = findAndSeekToOffset(columnIndex);
-
-		int length = (int) this.rowFromServer.readFieldLength();
-
-		return getDateFast(columnIndex, this.rowFromServer.getByteBuffer(),
-				offset, length, conn, rs);
-	}
-
-	public java.sql.Date getNativeDate(int columnIndex, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		return getNativeDate(columnIndex, this.rowFromServer.getByteBuffer(),
-				offset, (int) length, conn, rs);
-	}
-
-	public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar,
-			int jdbcType, int mysqlType, TimeZone tz,
-			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		return getNativeDateTimeValue(columnIndex, this.rowFromServer
-				.getByteBuffer(), offset, (int) length, targetCalendar, jdbcType,
-				mysqlType, tz, rollForward, conn, rs);
-	}
-
-	public Time getNativeTime(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		int offset = findAndSeekToOffset(columnIndex);
-
-		long length = this.rowFromServer.readFieldLength();
-
-		if (length == Buffer.NULL_LENGTH) {
-			return null;
-		}
-
-		return getNativeTime(columnIndex, this.rowFromServer.getByteBuffer(),
-				offset, (int) length, targetCalendar, tz, rollForward, conn, rs);
-	}
-}
\ No newline at end of file

Copied: branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRow.java (from rev 6449, branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java)
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java	2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRow.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -0,0 +1,278 @@
+/*
+ Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ */
+package com.mysql.jdbc;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.sql.Date;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * A RowHolder implementation that is for cached results (a-la
+ * mysql_store_result()).
+ * 
+ * @version $Id: $
+ */
+public class ByteArrayRow extends ResultSetRow {
+
+	byte[][] internalRowData;
+
+	public ByteArrayRow(byte[][] internalRowData) {
+		this.internalRowData = internalRowData;
+	}
+
+	public byte[] getColumnValue(int index) throws SQLException {
+		return this.internalRowData[index];
+	}
+
+	public void setColumnValue(int index, byte[] value) throws SQLException {
+		this.internalRowData[index] = value;
+	}
+
+	public String getString(int index, String encoding, ConnectionImpl conn)
+			throws SQLException {
+		byte[] columnData = this.internalRowData[index];
+
+		if (columnData == null) {
+			return null;
+		}
+
+		return getString(encoding, conn, columnData, 0, columnData.length);
+	}
+
+	public boolean isNull(int index) throws SQLException {
+		return this.internalRowData[index] == null;
+	}
+
+	public boolean isFloatingPointNumber(int index) throws SQLException {
+		byte[] numAsBytes = this.internalRowData[index];
+
+		if (this.internalRowData[index] == null
+				|| this.internalRowData[index].length == 0) {
+			return false;
+		}
+
+		for (int i = 0; i < numAsBytes.length; i++) {
+			if (((char) numAsBytes[i] == 'e') || ((char) numAsBytes[i] == 'E')) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	public long length(int index) throws SQLException {
+		if (this.internalRowData[index] == null) {
+			return 0;
+		}
+
+		return this.internalRowData[index].length;
+	}
+
+	public int getInt(int columnIndex) {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return StringUtils.getInt(this.internalRowData[columnIndex]);
+	}
+
+	public long getLong(int columnIndex) {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return StringUtils.getLong(this.internalRowData[columnIndex]);
+	}
+
+	public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getTimestampFast(columnIndex, this.internalRowData[columnIndex],
+				0, columnValue.length, targetCalendar, tz, rollForward, conn,
+				rs);
+	}
+
+	public double getNativeDouble(int columnIndex) throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return getNativeDouble(this.internalRowData[columnIndex], 0);
+	}
+
+	public float getNativeFloat(int columnIndex) throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return getNativeFloat(this.internalRowData[columnIndex], 0);
+	}
+
+	public int getNativeInt(int columnIndex) throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return getNativeInt(this.internalRowData[columnIndex], 0);
+	}
+
+	public long getNativeLong(int columnIndex) throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return getNativeLong(this.internalRowData[columnIndex], 0);
+	}
+
+	public short getNativeShort(int columnIndex) throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return 0;
+		}
+
+		return getNativeShort(this.internalRowData[columnIndex], 0);
+	}
+
+	public Timestamp getNativeTimestamp(int columnIndex,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
+		byte[] bits = this.internalRowData[columnIndex];
+
+		if (bits == null) {
+			return null;
+		}
+
+		return getNativeTimestamp(bits, 0, bits.length, targetCalendar, tz,
+				rollForward, conn, rs);
+	}
+
+	public void closeOpenStreams() {
+		// no-op for this type
+	}
+
+	public InputStream getBinaryInputStream(int columnIndex)
+			throws SQLException {
+		if (this.internalRowData[columnIndex] == null) {
+			return null;
+		}
+
+		return new ByteArrayInputStream(this.internalRowData[columnIndex]);
+	}
+
+	public Reader getReader(int columnIndex) throws SQLException {
+		InputStream stream = getBinaryInputStream(columnIndex);
+
+		if (stream == null) {
+			return null;
+		}
+
+		try {
+			return new InputStreamReader(stream, this.metadata[columnIndex]
+					.getCharacterSet());
+		} catch (UnsupportedEncodingException e) {
+			SQLException sqlEx = SQLError.createSQLException("");
+
+			sqlEx.initCause(e);
+
+			throw sqlEx;
+		}
+	}
+
+	public Time getTimeFast(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getTimeFast(columnIndex, this.internalRowData[columnIndex], 0,
+				columnValue.length, targetCalendar, tz, rollForward, conn, rs);
+	}
+
+	public Date getDateFast(int columnIndex, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getDateFast(columnIndex, this.internalRowData[columnIndex], 0,
+				columnValue.length, conn, rs);
+	}
+
+	public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar,
+			int jdbcType, int mysqlType, TimeZone tz,
+			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getNativeDateTimeValue(columnIndex, columnValue, 0,
+				columnValue.length, targetCalendar, jdbcType, mysqlType, tz,
+				rollForward, conn, rs);
+	}
+
+	public Date getNativeDate(int columnIndex, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getNativeDate(columnIndex, columnValue, 0, columnValue.length,
+				conn, rs);
+	}
+
+	public Time getNativeTime(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+		byte[] columnValue = this.internalRowData[columnIndex];
+
+		if (columnValue == null) {
+			return null;
+		}
+
+		return getNativeTime(columnIndex, columnValue, 0, columnValue.length,
+				targetCalendar, tz, rollForward, conn, rs);
+	}
+}
\ No newline at end of file

Deleted: branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/ByteArrayRowHolder.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1,278 +0,0 @@
-/*
- Copyright (C) 2007 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as 
- published by the Free Software Foundation.
-
- There are special exceptions to the terms and conditions of the GPL 
- as it is applied to this software. View the full text of the 
- exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
- software distribution.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- 
- */
-package com.mysql.jdbc;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.sql.Date;
-import java.sql.SQLException;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.TimeZone;
-
-/**
- * A RowHolder implementation that is for cached results (a-la
- * mysql_store_result()).
- * 
- * @version $Id: $
- */
-public class ByteArrayRowHolder extends RowHolder {
-
-	byte[][] internalRowData;
-
-	public ByteArrayRowHolder(byte[][] internalRowData) {
-		this.internalRowData = internalRowData;
-	}
-
-	public byte[] getColumnValue(int index) throws SQLException {
-		return this.internalRowData[index];
-	}
-
-	public void setColumnValue(int index, byte[] value) throws SQLException {
-		this.internalRowData[index] = value;
-	}
-
-	public String getString(int index, String encoding, ConnectionImpl conn)
-			throws SQLException {
-		byte[] columnData = this.internalRowData[index];
-
-		if (columnData == null) {
-			return null;
-		}
-
-		return getString(encoding, conn, columnData, 0, columnData.length);
-	}
-
-	public boolean isNull(int index) throws SQLException {
-		return this.internalRowData[index] == null;
-	}
-
-	public boolean isFloatingPointNumber(int index) throws SQLException {
-		byte[] numAsBytes = this.internalRowData[index];
-
-		if (this.internalRowData[index] == null
-				|| this.internalRowData[index].length == 0) {
-			return false;
-		}
-
-		for (int i = 0; i < numAsBytes.length; i++) {
-			if (((char) numAsBytes[i] == 'e') || ((char) numAsBytes[i] == 'E')) {
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	public long length(int index) throws SQLException {
-		if (this.internalRowData[index] == null) {
-			return 0;
-		}
-
-		return this.internalRowData[index].length;
-	}
-
-	public int getInt(int columnIndex) {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return StringUtils.getInt(this.internalRowData[columnIndex]);
-	}
-
-	public long getLong(int columnIndex) {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return StringUtils.getLong(this.internalRowData[columnIndex]);
-	}
-
-	public Timestamp getTimestampFast(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getTimestampFast(columnIndex, this.internalRowData[columnIndex],
-				0, columnValue.length, targetCalendar, tz, rollForward, conn,
-				rs);
-	}
-
-	public double getNativeDouble(int columnIndex) throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return getNativeDouble(this.internalRowData[columnIndex], 0);
-	}
-
-	public float getNativeFloat(int columnIndex) throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return getNativeFloat(this.internalRowData[columnIndex], 0);
-	}
-
-	public int getNativeInt(int columnIndex) throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return getNativeInt(this.internalRowData[columnIndex], 0);
-	}
-
-	public long getNativeLong(int columnIndex) throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return getNativeLong(this.internalRowData[columnIndex], 0);
-	}
-
-	public short getNativeShort(int columnIndex) throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return 0;
-		}
-
-		return getNativeShort(this.internalRowData[columnIndex], 0);
-	}
-
-	public Timestamp getNativeTimestamp(int columnIndex,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
-		byte[] bits = this.internalRowData[columnIndex];
-
-		if (bits == null) {
-			return null;
-		}
-
-		return getNativeTimestamp(bits, 0, bits.length, targetCalendar, tz,
-				rollForward, conn, rs);
-	}
-
-	public void closeOpenStreams() {
-		// no-op for this type
-	}
-
-	public InputStream getBinaryInputStream(int columnIndex)
-			throws SQLException {
-		if (this.internalRowData[columnIndex] == null) {
-			return null;
-		}
-
-		return new ByteArrayInputStream(this.internalRowData[columnIndex]);
-	}
-
-	public Reader getReader(int columnIndex) throws SQLException {
-		InputStream stream = getBinaryInputStream(columnIndex);
-
-		if (stream == null) {
-			return null;
-		}
-
-		try {
-			return new InputStreamReader(stream, this.metadata[columnIndex]
-					.getCharacterSet());
-		} catch (UnsupportedEncodingException e) {
-			SQLException sqlEx = SQLError.createSQLException("");
-
-			sqlEx.initCause(e);
-
-			throw sqlEx;
-		}
-	}
-
-	public Time getTimeFast(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getTimeFast(columnIndex, this.internalRowData[columnIndex], 0,
-				columnValue.length, targetCalendar, tz, rollForward, conn, rs);
-	}
-
-	public Date getDateFast(int columnIndex, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getDateFast(columnIndex, this.internalRowData[columnIndex], 0,
-				columnValue.length, conn, rs);
-	}
-
-	public Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar,
-			int jdbcType, int mysqlType, TimeZone tz,
-			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getNativeDateTimeValue(columnIndex, columnValue, 0,
-				columnValue.length, targetCalendar, jdbcType, mysqlType, tz,
-				rollForward, conn, rs);
-	}
-
-	public Date getNativeDate(int columnIndex, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getNativeDate(columnIndex, columnValue, 0, columnValue.length,
-				conn, rs);
-	}
-
-	public Time getNativeTime(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-		byte[] columnValue = this.internalRowData[columnIndex];
-
-		if (columnValue == null) {
-			return null;
-		}
-
-		return getNativeTime(columnIndex, columnValue, 0, columnValue.length,
-				targetCalendar, tz, rollForward, conn, rs);
-	}
-}
\ No newline at end of file

Deleted: branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1,476 +0,0 @@
-/*
- Copyright (C) 2002-2006 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as 
- published by the Free Software Foundation.
-
- There are special exceptions to the terms and conditions of the GPL 
- as it is applied to this software. View the full text of the 
- exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
- software distribution.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-package com.mysql.jdbc;
-
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Model for result set data backed by a cursor. Only works for forward-only
- * result sets (but still works with updatable concurrency).
- * 
- * @version $Id: CursorRowProvider.java,v 1.1.2.1 2005/05/19 18:31:49 mmatthews
- *          Exp $
- */
-public class CursorRowProvider implements RowData {
-
-	private final static int BEFORE_START_OF_ROWS = -1;
-
-	/**
-	 * The cache of rows we have retrieved from the server.
-	 */
-	private List fetchedRows;
-
-	/**
-	 * Where we are positionaly in the entire result set, used mostly to
-	 * facilitate easy 'isBeforeFirst()' and 'isFirst()' methods.
-	 */
-	private int currentPositionInEntireResult = BEFORE_START_OF_ROWS;
-
-	/**
-	 * Position in cache of rows, used to determine if we need to fetch more
-	 * rows from the server to satisfy a request for the next row.
-	 */
-	private int currentPositionInFetchedRows = BEFORE_START_OF_ROWS;
-
-	/**
-	 * The result set that we 'belong' to.
-	 */
-	private ResultSetImpl owner;
-
-	/**
-	 * Have we been told from the server that we have seen the last row?
-	 */
-	private boolean lastRowFetched = false;
-
-	/**
-	 * Field-level metadata from the server. We need this, because it is not
-	 * sent for each batch of rows, but we need the metadata to unpack the
-	 * results for each field.
-	 */
-	private Field[] metadata;
-
-	/**
-	 * Communications channel to the server
-	 */
-	private MysqlIO mysql;
-
-	/**
-	 * Identifier for the statement that created this cursor.
-	 */
-	private long statementIdOnServer;
-
-	/**
-	 * The prepared statement that created this cursor.
-	 */
-	private ServerPreparedStatement prepStmt;
-
-	/**
-	 * The server status for 'last-row-sent'...This might belong in mysqldefs,
-	 * but it it only ever referenced from here.
-	 */
-	private static final int SERVER_STATUS_LAST_ROW_SENT = 128;
-
-	/**
-	 * Have we attempted to fetch any rows yet?
-	 */
-	private boolean firstFetchCompleted = false;
-
-	private boolean wasEmpty = false;
-
-	/**
-	 * Creates a new cursor-backed row provider.
-	 * 
-	 * @param ioChannel
-	 *            connection to the server.
-	 * @param creatingStatement
-	 *            statement that opened the cursor.
-	 * @param metadata
-	 *            field-level metadata for the results that this cursor covers.
-	 */
-	public CursorRowProvider(MysqlIO ioChannel,
-			ServerPreparedStatement creatingStatement, Field[] metadata) {
-		this.currentPositionInEntireResult = BEFORE_START_OF_ROWS;
-		this.metadata = metadata;
-		this.mysql = ioChannel;
-		this.statementIdOnServer = creatingStatement.getServerStatementId();
-		this.prepStmt = creatingStatement;
-	}
-
-	/**
-	 * Returns true if we got the last element.
-	 * 
-	 * @return DOCUMENT ME!
-	 */
-	public boolean isAfterLast() {
-		return lastRowFetched
-				&& this.currentPositionInFetchedRows > this.fetchedRows.size();
-	}
-
-	/**
-	 * Only works on non dynamic result sets.
-	 * 
-	 * @param index
-	 *            row number to get at
-	 * @return row data at index
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public RowHolder getAt(int ind) throws SQLException {
-		notSupported();
-
-		return null;
-	}
-
-	/**
-	 * Returns if iteration has not occured yet.
-	 * 
-	 * @return true if before first row
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public boolean isBeforeFirst() throws SQLException {
-		return this.currentPositionInEntireResult < 0;
-	}
-
-	/**
-	 * Moves the current position in the result set to the given row number.
-	 * 
-	 * @param rowNumber
-	 *            row to move to
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void setCurrentRow(int rowNumber) throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Returns the current position in the result set as a row number.
-	 * 
-	 * @return the current row number
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public int getCurrentRowNumber() throws SQLException {
-		return this.currentPositionInEntireResult + 1;
-	}
-
-	/**
-	 * Returns true if the result set is dynamic.
-	 * 
-	 * This means that move back and move forward won't work because we do not
-	 * hold on to the records.
-	 * 
-	 * @return true if this result set is streaming from the server
-	 */
-	public boolean isDynamic() {
-		return true;
-	}
-
-	/**
-	 * Has no records.
-	 * 
-	 * @return true if no records
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public boolean isEmpty() throws SQLException {
-		return this.isBeforeFirst() && this.isAfterLast();
-	}
-
-	/**
-	 * Are we on the first row of the result set?
-	 * 
-	 * @return true if on first row
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public boolean isFirst() throws SQLException {
-		return this.currentPositionInEntireResult == 0;
-	}
-
-	/**
-	 * Are we on the last row of the result set?
-	 * 
-	 * @return true if on last row
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public boolean isLast() throws SQLException {
-		return this.lastRowFetched
-				&& this.currentPositionInFetchedRows == (this.fetchedRows
-						.size() - 1);
-	}
-
-	/**
-	 * Adds a row to this row data.
-	 * 
-	 * @param row
-	 *            the row to add
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void addRow(RowHolder row) throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Moves to after last.
-	 * 
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void afterLast() throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Moves to before first.
-	 * 
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void beforeFirst() throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Moves to before last so next el is the last el.
-	 * 
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void beforeLast() throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * We're done.
-	 * 
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void close() throws SQLException {
-
-		this.metadata = null;
-		this.owner = null;
-	}
-
-	/**
-	 * Returns true if another row exists.
-	 * 
-	 * @return true if more rows
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public boolean hasNext() throws SQLException {
-
-		if (this.fetchedRows != null && this.fetchedRows.size() == 0) {
-			return false;
-		}
-
-		if (this.owner != null && this.owner.owningStatement != null) {
-			int maxRows = this.owner.owningStatement.maxRows;
-			
-			if (maxRows != -1 && this.currentPositionInEntireResult + 1 > maxRows) {
-				return false;
-			}	
-		}
-		
-		if (this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) {
-			// Case, we've fetched some rows, but are not at end of fetched
-			// block
-			if (this.currentPositionInFetchedRows < (this.fetchedRows.size() - 1)) {
-				return true;
-			} else if (this.currentPositionInFetchedRows == this.fetchedRows
-					.size()
-					&& this.lastRowFetched) {
-				return false;
-			} else {
-				// need to fetch to determine
-				fetchMoreRows();
-
-				return (this.fetchedRows.size() > 0);
-			}
-		}
-
-		// Okay, no rows _yet_, so fetch 'em
-
-		fetchMoreRows();
-
-		return this.fetchedRows.size() > 0;
-	}
-
-	/**
-	 * Moves the current position relative 'rows' from the current position.
-	 * 
-	 * @param rows
-	 *            the relative number of rows to move
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void moveRowRelative(int rows) throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Returns the next row.
-	 * 
-	 * @return the next row value
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public RowHolder next() throws SQLException {
-		if (this.fetchedRows == null && this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) {
-			throw SQLError.createSQLException(
-					Messages
-							.getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
-					SQLError.SQL_STATE_GENERAL_ERROR);
-		}
-		
-		if (!hasNext()) {
-			return null;
-		}
-		
-		this.currentPositionInEntireResult++;
-		this.currentPositionInFetchedRows++;
-
-		// Catch the forced scroll-passed-end
-		if (this.fetchedRows != null && this.fetchedRows.size() == 0) {
-			return null;
-		}
-
-		if (this.currentPositionInFetchedRows > (this.fetchedRows.size() - 1)) {
-			fetchMoreRows();
-			this.currentPositionInFetchedRows = 0;
-		}
-
-		RowHolder row = (RowHolder) this.fetchedRows
-				.get(this.currentPositionInFetchedRows);
-
-		row.setMetadata(this.metadata);
-		
-		return row;
-	}
-
-	/**
-	 * 
-	 */
-	private void fetchMoreRows() throws SQLException {
-		if (this.lastRowFetched) {
-			this.fetchedRows = new ArrayList(0);
-			return;
-		}
-
-		synchronized (this.owner.connection.getMutex()) {
-			boolean oldFirstFetchCompleted = this.firstFetchCompleted;
-			
-			if (!this.firstFetchCompleted) {
-				this.firstFetchCompleted = true;
-			}
-
-			int numRowsToFetch = this.owner.getFetchSize();
-
-			if (numRowsToFetch == 0) {
-				numRowsToFetch = this.prepStmt.getFetchSize();
-			}
-			
-			if (numRowsToFetch == Integer.MIN_VALUE) {
-				// Handle the case where the user used 'old'
-				// streaming result sets
-
-				numRowsToFetch = 1;
-			}
-
-			this.fetchedRows = this.mysql.fetchRowsViaCursor(this.fetchedRows,
-					this.statementIdOnServer, this.metadata, numRowsToFetch);
-			this.currentPositionInFetchedRows = BEFORE_START_OF_ROWS;
-
-			if ((this.mysql.getServerStatus() & SERVER_STATUS_LAST_ROW_SENT) != 0) {
-				this.lastRowFetched = true;
-				
-				if (!oldFirstFetchCompleted && this.fetchedRows.size() == 0) {
-					this.wasEmpty  = true;
-				}
-			}
-		}
-	}
-
-	/**
-	 * Removes the row at the given index.
-	 * 
-	 * @param index
-	 *            the row to move to
-	 * @throws SQLException
-	 *             if a database error occurs
-	 */
-	public void removeRow(int ind) throws SQLException {
-		notSupported();
-	}
-
-	/**
-	 * Only works on non dynamic result sets.
-	 * 
-	 * @return the size of this row data
-	 */
-	public int size() {
-		return RESULT_SET_SIZE_UNKNOWN;
-	}
-
-	private void nextRecord() throws SQLException {
-
-	}
-
-	private void notSupported() throws SQLException {
-		throw new OperationNotSupportedException();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.mysql.jdbc.RowProvider#setOwner(com.mysql.jdbc.ResultSet)
-	 */
-	public void setOwner(ResultSetImpl rs) {
-		this.owner = rs;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.mysql.jdbc.RowProvider#getOwner()
-	 */
-	public ResultSetInternalMethods getOwner() {
-		return this.owner;
-	}
-
-	public boolean wasEmpty() {
-		return this.wasEmpty;
-	}
-	
-	public void setMetadata(Field[] metadata) {
-		this.metadata = metadata;
-	}
-
-}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/DatabaseMetaData.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -771,7 +771,7 @@
 					rowData[5] = s2b(functionName);                      // SPECFIC NAME
 				}
 
-				procedureRowsOrderedByName.put(functionName, new ByteArrayRowHolder(rowData));
+				procedureRowsOrderedByName.put(functionName, new ByteArrayRow(rowData));
 			}
 		}
 	}
@@ -816,12 +816,12 @@
 						.toString(procedureReturnsResult) : Integer
 						.toString(procedureResultUnknown));
 
-				procedureRowsOrderedByName.put(procedureName, new ByteArrayRowHolder(rowData));
+				procedureRowsOrderedByName.put(procedureName, new ByteArrayRow(rowData));
 			}
 		}
 	}
 
-	private RowHolder convertTypeDescriptorToProcedureRow(
+	private ResultSetRow convertTypeDescriptorToProcedureRow(
 			byte[] procNameAsBytes, String paramName, boolean isOutParam,
 			boolean isInParam, boolean isReturnParam, TypeDescriptor typeDesc,
 			boolean forGetFunctionColumns,
@@ -893,7 +893,7 @@
 			row[16] = s2b(paramName);
 		}
 		
-		return new ByteArrayRowHolder(row);
+		return new ByteArrayRow(row);
 	}
 
 	/**
@@ -1098,7 +1098,7 @@
 		}
 	
 		row[2] = s2b(commentBuf.toString());
-		rows.add(new ByteArrayRowHolder(row));
+		rows.add(new ByteArrayRow(row));
 	
 		return rows;
 	}
@@ -1390,7 +1390,7 @@
 													java.sql.DatabaseMetaData.bestRowNotPseudo)
 											.getBytes();
 
-									rows.add(new ByteArrayRowHolder(rowVal));
+									rows.add(new ByteArrayRow(rowVal));
 								}
 							}
 						}
@@ -1792,7 +1792,7 @@
 							parameterNamePattern);
 
 					if (wildCompareRes != StringUtils.WILD_COMPARE_NO_MATCH) {
-						RowHolder row = convertTypeDescriptorToProcedureRow(
+						ResultSetRow row = convertTypeDescriptorToProcedureRow(
 								procNameAsBytes, paramName, isOutParam,
 								isInParam, false, typeDesc, forGetFunctionColumns,
 								ordinal++);
@@ -2036,7 +2036,7 @@
 			while (results.next()) {
 				byte[][] rowVal = new byte[1][];
 				rowVal[0] = results.getBytes(1);
-				tuples.add(new ByteArrayRowHolder(rowVal));
+				tuples.add(new ByteArrayRow(rowVal));
 			}
 
 			return buildResultSet(fields, tuples);
@@ -2210,7 +2210,7 @@
 						tuple[5] = s2b(fullUser.toString());
 						tuple[6] = s2b(privilege);
 						tuple[7] = null;
-						grantRows.add(new ByteArrayRowHolder(tuple));
+						grantRows.add(new ByteArrayRow(tuple));
 					}
 				}
 			}
@@ -2551,7 +2551,7 @@
 
 								rowVal[17] = s2b(typeDesc.isNullable);
 
-								rows.add(new ByteArrayRowHolder(rowVal));
+								rows.add(new ByteArrayRow(rowVal));
 							}
 						} finally {
 							if (results != null) {
@@ -2808,7 +2808,7 @@
 														.toString(
 																java.sql.DatabaseMetaData.importedKeyNotDeferrable)
 														.getBytes();
-												tuples.add(new ByteArrayRowHolder(tuple));
+												tuples.add(new ByteArrayRow(tuple));
 												keySeq++;
 											}
 										}
@@ -3553,11 +3553,11 @@
 
 							if (unique) {
 								if (indexIsUnique) {
-									rows.add(new ByteArrayRowHolder(row));
+									rows.add(new ByteArrayRow(row));
 								}
 							} else {
 								// All rows match
-								rows.add(new ByteArrayRowHolder(row));
+								rows.add(new ByteArrayRow(row));
 							}
 						}
 					} finally {
@@ -3922,7 +3922,7 @@
 						Iterator sortedIterator = sortMap.values().iterator();
 
 						while (sortedIterator.hasNext()) {
-							rows.add(new ByteArrayRowHolder((byte[][])sortedIterator.next()));
+							rows.add(new ByteArrayRow((byte[][])sortedIterator.next()));
 						}
 
 					} finally {
@@ -4395,7 +4395,7 @@
 			tuple[PK_NAME] = null; // not available from show table status
 			tuple[DEFERRABILITY] = s2b(Integer
 					.toString(java.sql.DatabaseMetaData.importedKeyNotDeferrable));
-			tuples.add(new ByteArrayRowHolder(tuple));
+			tuples.add(new ByteArrayRow(tuple));
 		}
 	}
 
@@ -4676,7 +4676,7 @@
 								tuple[4] = s2b(fullUser.toString());
 								tuple[5] = s2b(privilege);
 								tuple[6] = null;
-								grantRows.add(new ByteArrayRowHolder(tuple));
+								grantRows.add(new ByteArrayRow(tuple));
 							}
 						} finally {
 							if (columnResults != null) {
@@ -4934,7 +4934,7 @@
 									.iterator();
 
 							while (tablesIter.hasNext()) {
-								tuples.add(new ByteArrayRowHolder((byte[][])tablesIter.next()));
+								tuples.add(new ByteArrayRow((byte[][])tablesIter.next()));
 							}
 						}
 
@@ -4943,7 +4943,7 @@
 									.iterator();
 
 							while (viewsIter.hasNext()) {
-								tuples.add(new ByteArrayRowHolder((byte[][])viewsIter.next()));
+								tuples.add(new ByteArrayRow((byte[][])viewsIter.next()));
 							}
 						}
 
@@ -4996,17 +4996,17 @@
 
 		byte[][] tableTypeRow = new byte[1][];
 		tableTypeRow[0] = TABLE_AS_BYTES;
-		tuples.add(new ByteArrayRowHolder(tableTypeRow));
+		tuples.add(new ByteArrayRow(tableTypeRow));
 
 		if (this.conn.versionMeetsMinimum(5, 0, 1)) {
 			byte[][] viewTypeRow = new byte[1][];
 			viewTypeRow[0] = VIEW_AS_BYTES;
-			tuples.add(new ByteArrayRowHolder(viewTypeRow));
+			tuples.add(new ByteArrayRow(viewTypeRow));
 		}
 
 		byte[][] tempTypeRow = new byte[1][];
 		tempTypeRow[0] = s2b("LOCAL TEMPORARY");
-		tuples.add(new ByteArrayRowHolder(tempTypeRow));
+		tuples.add(new ByteArrayRow(tempTypeRow));
 
 		return buildResultSet(fields, tuples);
 	}
@@ -5185,7 +5185,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: BOOL (silently converted to TINYINT(1)) JDBC Type: BIT
@@ -5217,7 +5217,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TINYINT JDBC Type: TINYINT
@@ -5249,7 +5249,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: BIGINT JDBC Type: BIGINT
@@ -5281,7 +5281,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: LONG VARBINARY JDBC Type: LONGVARBINARY
@@ -5313,7 +5313,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: MEDIUMBLOB JDBC Type: LONGVARBINARY
@@ -5345,7 +5345,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: LONGBLOB JDBC Type: LONGVARBINARY
@@ -5379,7 +5379,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: BLOB JDBC Type: LONGVARBINARY
@@ -5411,7 +5411,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TINYBLOB JDBC Type: LONGVARBINARY
@@ -5443,7 +5443,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: VARBINARY (sliently converted to VARCHAR(M) BINARY) JDBC
@@ -5476,7 +5476,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: BINARY (silently converted to CHAR(M) BINARY) JDBC Type:
@@ -5509,7 +5509,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: LONG VARCHAR JDBC Type: LONGVARCHAR
@@ -5541,7 +5541,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: MEDIUMTEXT JDBC Type: LONGVARCHAR
@@ -5573,7 +5573,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: LONGTEXT JDBC Type: LONGVARCHAR
@@ -5607,7 +5607,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TEXT JDBC Type: LONGVARCHAR
@@ -5639,7 +5639,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TINYTEXT JDBC Type: LONGVARCHAR
@@ -5671,7 +5671,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: CHAR JDBC Type: CHAR
@@ -5703,7 +5703,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: NUMERIC (silently converted to DECIMAL) JDBC Type:
@@ -5736,7 +5736,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: DECIMAL JDBC Type: DECIMAL
@@ -5768,7 +5768,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: INTEGER JDBC Type: INTEGER
@@ -5800,7 +5800,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: INT JDBC Type: INTEGER
@@ -5832,7 +5832,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: MEDIUMINT JDBC Type: INTEGER
@@ -5864,7 +5864,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: SMALLINT JDBC Type: SMALLINT
@@ -5896,7 +5896,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: FLOAT JDBC Type: REAL (this is the SINGLE PERCISION
@@ -5929,7 +5929,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: DOUBLE JDBC Type: DOUBLE
@@ -5961,7 +5961,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: DOUBLE PRECISION JDBC Type: DOUBLE
@@ -5993,7 +5993,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: REAL (does not map to Types.REAL) JDBC Type: DOUBLE
@@ -6025,7 +6025,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: VARCHAR JDBC Type: VARCHAR
@@ -6057,7 +6057,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: ENUM JDBC Type: VARCHAR
@@ -6089,7 +6089,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: SET JDBC Type: VARCHAR
@@ -6121,7 +6121,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: DATE JDBC Type: DATE
@@ -6153,7 +6153,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TIME JDBC Type: TIME
@@ -6185,7 +6185,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: DATETIME JDBC Type: TIMESTAMP
@@ -6217,7 +6217,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		/*
 		 * MySQL Type: TIMESTAMP JDBC Type: TIMESTAMP
@@ -6249,7 +6249,7 @@
 		rowVal[15] = s2b("0"); // SQL Data Type (not used)
 		rowVal[16] = s2b("0"); // SQL DATETIME SUB (not used)
 		rowVal[17] = s2b("10"); // NUM_PREC_RADIX (2 or 10)
-		tuples.add(new ByteArrayRowHolder(rowVal));
+		tuples.add(new ByteArrayRow(rowVal));
 
 		return buildResultSet(fields, tuples);
 	}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlIO.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlIO.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/MysqlIO.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -448,7 +448,7 @@
 			}
 			
 			if (usingCursor) {
-				RowData rows = new CursorRowProvider(
+				RowData rows = new RowDataCursor(
 					this,
 					prepStmt,
 					fields);
@@ -1372,7 +1372,7 @@
     *
     * @throws SQLException DOCUMENT ME!
     */
-    final RowHolder nextRow(Field[] fields, int columnCount,
+    final ResultSetRow nextRow(Field[] fields, int columnCount,
         boolean isBinaryEncoded, int resultSetConcurrency, 
         boolean useBufferRowHolderIfPossible,
         boolean reuseRowPacket,
@@ -1416,14 +1416,14 @@
             			rowData[i] = rowPacket.readLenByteArray(0);
             		}
 
-            		return new ByteArrayRowHolder(rowData);
+            		return new ByteArrayRow(rowData);
             	}
             		
             	if (!reuseRowPacket) {
             		this.reusablePacket = new Buffer(rowPacket.getBufLength());
             	}
             	
-            	return new BufferRowHolder(rowPacket, fields, false);
+            	return new BufferRow(rowPacket, fields, false);
 
             }
 
@@ -1447,7 +1447,7 @@
         		this.reusablePacket = new Buffer(rowPacket.getBufLength());
         	}
             	
-            return new BufferRowHolder(rowPacket, fields, true);
+            return new BufferRow(rowPacket, fields, true);
         }
 
         rowPacket.setPosition(rowPacket.getPosition() - 1);
@@ -1456,7 +1456,7 @@
         return null;
     }
     
-    final RowHolder nextRowFast(Field[] fields, int columnCount,
+    final ResultSetRow nextRowFast(Field[] fields, int columnCount,
             boolean isBinaryEncoded, int resultSetConcurrency, 
             boolean useBufferRowHolderIfPossible,
             boolean reuseRowPacket)
@@ -1590,7 +1590,7 @@
 				skipFully(this.mysqlInput, remaining);
 			}
 
-			return new ByteArrayRowHolder(rowData);
+			return new ByteArrayRow(rowData);
 		} catch (IOException ioEx) {
 			throw SQLError.createCommunicationsException(this.connection,
     				this.lastPacketSentTimeMs, ioEx);
@@ -3743,7 +3743,7 @@
      *
      * @throws SQLException DOCUMENT ME!
      */
-    private final RowHolder unpackBinaryResultSetRow(Field[] fields,
+    private final ResultSetRow unpackBinaryResultSetRow(Field[] fields,
         Buffer binaryData, int resultSetConcurrency) throws SQLException {
         int numFields = fields.length;
 
@@ -3790,7 +3790,7 @@
         	}
         }
 
-        return new ByteArrayRowHolder(unpackedRowData);
+        return new ByteArrayRow(unpackedRowData);
     }
 
         
@@ -4321,7 +4321,7 @@
 		sendCommand(MysqlDefs.COM_FETCH, null, this.sharedSendPacket, true,
 				null);
 	
-		RowHolder row = null;
+		ResultSetRow row = null;
 	
 		while ((row = nextRow(columnTypes, columnTypes.length, true,
 				ResultSet.CONCUR_READ_ONLY, false, true, null)) != null) {

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/PreparedStatement.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1318,7 +1318,7 @@
 
 								while (rs.next()) {
 									this.batchedGeneratedKeys
-											.add(new ByteArrayRowHolder(new byte[][] { rs.getBytes(1) }));
+											.add(new ByteArrayRow(new byte[][] { rs.getBytes(1) }));
 								}
 							} finally {
 								if (rs != null) {
@@ -4558,7 +4558,7 @@
 				typeMetadata[i] = parameterMetadata;
 			}
 
-			rows.add(new ByteArrayRowHolder(rowData));
+			rows.add(new ByteArrayRow(rowData));
 
 			this.bindingsAsRs = new ResultSetImpl(connection.getCatalog(),
 					typeMetadata, new RowDataStatic(rows), connection, null);

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetImpl.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetImpl.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetImpl.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -294,7 +294,7 @@
 	PreparedStatement statementUsedForFetchingRows;
 
 	/** Pointer to current row data */
-	protected RowHolder thisRow = null; // Values for current row
+	protected ResultSetRow thisRow = null; // Values for current row
 
 	// These are longs for
 	// recent versions of the MySQL server.
@@ -586,6 +586,10 @@
 				this.doingUpdates = false;
 			}
 
+			if (this.thisRow != null) {
+				this.thisRow.closeOpenStreams();
+			}
+			
 			if (row == 1) {
 				b = first();
 			} else if (row == -1) {
@@ -639,6 +643,10 @@
 			this.doingUpdates = false;
 		}
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		if (this.rowData.size() != 0) {
 			this.rowData.afterLast();
 			this.thisRow = null;
@@ -672,6 +680,10 @@
 			return;
 		}
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		this.rowData.beforeFirst();
 		this.thisRow = null;
 	}
@@ -6913,6 +6925,10 @@
 			this.doingUpdates = false;
 		}
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		this.rowData.beforeLast();
 		this.thisRow = this.rowData.next();
 
@@ -6997,6 +7013,10 @@
 					SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
 		}
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		if (this.rowData.size() == 0) {
 			b = false;
 		} else {
@@ -7010,17 +7030,6 @@
 				b = true;
 				
 			}
-			
-			/*
-			if (!this.rowData.hasNext()) {
-				// force scroll past end
-				this.rowData.next();
-				b = false;
-			} else {
-				clearWarnings();
-				this.thisRow = this.rowData.next();
-				b = true;
-			} */
 		}
 
 		return b;
@@ -7245,6 +7254,10 @@
 
 		int rowIndex = this.rowData.getCurrentRowNumber();
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		if ((rowIndex - 1) >= 0) {
 			rowIndex--;
 			this.rowData.setCurrentRow(rowIndex);
@@ -7535,6 +7548,10 @@
 			return false;
 		}
 
+		if (this.thisRow != null) {
+			this.thisRow.closeOpenStreams();
+		}
+		
 		this.rowData.moveRowRelative(rows);
 		this.thisRow = this.rowData.getAt(this.rowData.getCurrentRowNumber());
 

Copied: branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetRow.java (from rev 6449, branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java)
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java	2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/ResultSetRow.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -0,0 +1,1371 @@
+/*
+ Copyright (C) 2007 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ 
+ */
+package com.mysql.jdbc;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Date;
+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.StringTokenizer;
+import java.util.TimeZone;
+
+/**
+ * Classes that implement this interface represent one row of data from the
+ * MySQL server that might be stored in different ways depending on whether the
+ * result set was streaming (so they wrap a reusable packet), or whether the
+ * result set was cached or via a server-side cursor (so they represent a
+ * byte[][]).
+ * 
+ * Notice that <strong>no</strong> bounds checking is expected for implementors
+ * of this interface, it happens in ResultSetImpl.
+ * 
+ * @version $Id: $
+ */
+public abstract class ResultSetRow {
+	/**
+	 * The metadata of the fields of this result set.
+	 */
+	protected Field[] metadata;
+
+	/**
+	 * Called during navigation to next row to close all open
+	 * streams.
+	 */
+	public abstract void closeOpenStreams();
+
+	/**
+	 * Returns data at the given index as an InputStream with no
+	 * character conversion.
+	 * 
+	 * @param columnIndex
+	 *            of the column value (starting at 0) to return.
+	 * @return the value at the given index as an InputStream or null
+	 *         if null.
+	 *         
+	 * @throws SQLException if an error occurs while retrieving the value.
+	 */
+	public abstract InputStream getBinaryInputStream(int columnIndex)
+			throws SQLException;
+
+	/**
+	 * Returns the value at the given column (index starts at 0) "raw" (i.e.
+	 * as-returned by the server).
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to return.
+	 * @return the value for the given column (including NULL if it is)
+	 * @throws SQLException
+	 *             if an error occurs while retrieving the value.
+	 */
+	public abstract byte[] getColumnValue(int index) throws SQLException;
+
+	protected final java.sql.Date getDateFast(int columnIndex,
+			byte[] dateAsBytes, int offset, int length, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+
+		int year = 0;
+		int month = 0;
+		int day = 0;
+
+		try {
+			if (dateAsBytes == null) {
+				return null;
+			}
+
+			boolean allZeroDate = true;
+
+			boolean onlyTimePresent = false;
+
+			for (int i = 0; i < length; i++) {
+				if (dateAsBytes[offset + i] == ':') {
+					onlyTimePresent = true;
+					break;
+				}
+			}
+
+			for (int i = 0; i < length; i++) {
+				byte b = dateAsBytes[offset + i];
+
+				if (b == ' ' || b == '-' || b == '/') {
+					onlyTimePresent = false;
+				}
+
+				if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/'
+						&& b != '.') {
+					allZeroDate = false;
+
+					break;
+				}
+			}
+
+			if (!onlyTimePresent && allZeroDate) {
+
+				if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+						.equals(conn.getZeroDateTimeBehavior())) {
+
+					return null;
+				} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+						.equals(conn.getZeroDateTimeBehavior())) {
+					throw SQLError.createSQLException("Value '"
+							+ new String(dateAsBytes)
+							+ "' can not be represented as java.sql.Date",
+							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				}
+
+				// We're left with the case of 'round' to a date Java _can_
+				// represent, which is '0001-01-01'.
+				return rs.fastDateCreate(null, 1, 1, 1);
+
+			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
+				// Convert from TIMESTAMP
+				switch (length) {
+				case 21:
+				case 19: { // java.sql.Timestamp format
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 4);
+					month = StringUtils.getInt(dateAsBytes, offset + 5,
+							offset + 7);
+					day = StringUtils.getInt(dateAsBytes, offset + 8,
+							offset + 10);
+
+					return rs.fastDateCreate(null, year, month, day);
+				}
+
+				case 14:
+				case 8: {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 4);
+					month = StringUtils.getInt(dateAsBytes, offset + 4,
+							offset + 6);
+					day = StringUtils.getInt(dateAsBytes, offset + 6,
+							offset + 8);
+
+					return rs.fastDateCreate(null, year, month, day);
+				}
+
+				case 12:
+				case 10:
+				case 6: {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 2);
+
+					if (year <= 69) {
+						year = year + 100;
+					}
+
+					month = StringUtils.getInt(dateAsBytes, offset + 2,
+							offset + 4);
+					day = StringUtils.getInt(dateAsBytes, offset + 4,
+							offset + 6);
+
+					return rs.fastDateCreate(null, year + 1900, month, day);
+				}
+
+				case 4: {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 4);
+
+					if (year <= 69) {
+						year = year + 100;
+					}
+
+					month = StringUtils.getInt(dateAsBytes, offset + 2,
+							offset + 4);
+
+					return rs.fastDateCreate(null, year + 1900, month, 1);
+				}
+
+				case 2: {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 2);
+
+					if (year <= 69) {
+						year = year + 100;
+					}
+
+					return rs.fastDateCreate(null, year + 1900, 1, 1);
+				}
+
+				default:
+					throw SQLError
+							.createSQLException(
+									Messages
+											.getString(
+													"ResultSet.Bad_format_for_Date",
+													new Object[] {
+															new String(
+																	dateAsBytes),
+															Constants
+																	.integerValueOf(columnIndex + 1) }),
+									SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+				} /* endswitch */
+			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
+
+				if (length == 2 || length == 1) {
+					year = StringUtils.getInt(dateAsBytes, offset, offset
+							+ length);
+
+					if (year <= 69) {
+						year = year + 100;
+					}
+
+					year += 1900;
+				} else {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 4);
+				}
+
+				return rs.fastDateCreate(null, year, 1, 1);
+			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
+				return rs.fastDateCreate(null, 1970, 1, 1); // Return EPOCH
+			} else {
+				if (length < 10) {
+					if (length == 8) {
+						return rs.fastDateCreate(null, 1970, 1, 1); // Return
+						// EPOCH for
+						// TIME
+					}
+
+					throw SQLError
+							.createSQLException(
+									Messages
+											.getString(
+													"ResultSet.Bad_format_for_Date",
+													new Object[] {
+															new String(
+																	dateAsBytes),
+															Constants
+																	.integerValueOf(columnIndex + 1) }),
+									SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+				}
+
+				if (length != 18) {
+					year = StringUtils.getInt(dateAsBytes, offset + 0,
+							offset + 4);
+					month = StringUtils.getInt(dateAsBytes, offset + 5,
+							offset + 7);
+					day = StringUtils.getInt(dateAsBytes, offset + 8,
+							offset + 10);
+				} else {
+					// JDK-1.3 timestamp format, not real easy to parse
+					// positionally :p
+					StringTokenizer st = new StringTokenizer(new String(
+							dateAsBytes, offset, length, "ISO8859_1"), "- ");
+
+					year = Integer.parseInt(st.nextToken());
+					month = Integer.parseInt(st.nextToken());
+					day = Integer.parseInt(st.nextToken());
+				}
+			}
+
+			return rs.fastDateCreate(null, year, month, day);
+		} catch (SQLException sqlEx) {
+			throw sqlEx; // don't re-wrap
+		} catch (Exception e) {
+			throw SQLError.createSQLException(Messages.getString(
+					"ResultSet.Bad_format_for_Date", new Object[] {
+							new String(dateAsBytes),
+							Constants.integerValueOf(columnIndex + 1) }),
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
+		}
+	}
+
+	public abstract java.sql.Date getDateFast(int columnIndex,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
+
+	/**
+	 * Returns the value at the given column (index starts at 0) as an int. *
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to return.
+	 * @return the value for the given column (returns 0 if NULL, use isNull()
+	 *         to determine if the value was actually NULL)
+	 * @throws SQLException
+	 *             if an error occurs while retrieving the value.
+	 */
+	public abstract int getInt(int columnIndex) throws SQLException;
+
+	/**
+	 * Returns the value at the given column (index starts at 0) as a long. *
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to return.
+	 * @return the value for the given column (returns 0 if NULL, use isNull()
+	 *         to determine if the value was actually NULL)
+	 * @throws SQLException
+	 *             if an error occurs while retrieving the value.
+	 */
+	public abstract long getLong(int columnIndex) throws SQLException;
+
+	protected java.sql.Date getNativeDate(int columnIndex, byte[] bits,
+			int offset, int length, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException {
+
+		int year = 0;
+		int month = 0;
+		int day = 0;
+
+		if (length != 0) {
+			year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);
+
+			month = bits[offset + 2];
+			day = bits[offset + 3];
+		}
+
+		if ((year == 0) && (month == 0) && (day == 0)) {
+			if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+					.equals(conn.getZeroDateTimeBehavior())) {
+				return null;
+			} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+					.equals(conn.getZeroDateTimeBehavior())) {
+				throw SQLError
+						.createSQLException(
+								"Value '0000-00-00' can not be represented as java.sql.Date",
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+			}
+
+			year = 1;
+			month = 1;
+			day = 1;
+		}
+
+		return rs.fastDateCreate(rs.getCalendarInstanceForSessionOrNew(), year,
+				month, day);
+	}
+
+	public abstract Date getNativeDate(int columnIndex, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException;
+
+	protected Object getNativeDateTimeValue(int columnIndex, byte[] bits,
+			int offset, int length, Calendar targetCalendar, int jdbcType,
+			int mysqlType, TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException {
+
+		int year = 0;
+		int month = 0;
+		int day = 0;
+
+		int hour = 0;
+		int minute = 0;
+		int seconds = 0;
+
+		int nanos = 0;
+
+		if (bits == null) {
+
+			return null;
+		}
+
+		Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
+				.getUtcCalendar()
+				: rs.getCalendarInstanceForSessionOrNew();
+
+		boolean populatedFromDateTimeValue = false;
+
+		switch (mysqlType) {
+		case MysqlDefs.FIELD_TYPE_DATETIME:
+		case MysqlDefs.FIELD_TYPE_TIMESTAMP:
+			populatedFromDateTimeValue = true;
+
+			if (length != 0) {
+				year = (bits[offset + 0] & 0xff)
+						| ((bits[offset + 1] & 0xff) << 8);
+				month = bits[offset + 2];
+				day = bits[offset + 3];
+
+				if (length > 4) {
+					hour = bits[offset + 4];
+					minute = bits[offset + 5];
+					seconds = bits[offset + 6];
+				}
+
+				if (length > 7) {
+					// MySQL uses microseconds
+					nanos = ((bits[offset + 7] & 0xff)
+							| ((bits[offset + 8] & 0xff) << 8)
+							| ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
+				}
+			}
+
+			break;
+		case MysqlDefs.FIELD_TYPE_DATE:
+			populatedFromDateTimeValue = true;
+
+			if (bits.length != 0) {
+				year = (bits[offset + 0] & 0xff)
+						| ((bits[offset + 1] & 0xff) << 8);
+				month = bits[offset + 2];
+				day = bits[offset + 3];
+			}
+
+			break;
+		case MysqlDefs.FIELD_TYPE_TIME:
+			populatedFromDateTimeValue = true;
+
+			if (bits.length != 0) {
+				// bits[0] // skip tm->neg
+				// binaryData.readLong(); // skip daysPart
+				hour = bits[offset + 5];
+				minute = bits[offset + 6];
+				seconds = bits[offset + 7];
+			}
+
+			year = 1970;
+			month = 1;
+			day = 1;
+
+			break;
+		default:
+			populatedFromDateTimeValue = false;
+		}
+
+		switch (jdbcType) {
+		case Types.TIME:
+			if (populatedFromDateTimeValue) {
+				Time time = TimeUtil.fastTimeCreate(rs
+						.getCalendarInstanceForSessionOrNew(), hour, minute,
+						seconds);
+
+				Time adjustedTime = TimeUtil.changeTimezone(conn,
+						sessionCalendar, targetCalendar, time, conn
+								.getServerTimezoneTZ(), tz, rollForward);
+
+				return adjustedTime;
+			}
+
+			return rs.getNativeTimeViaParseConversion(columnIndex + 1,
+					targetCalendar, tz, rollForward);
+
+		case Types.DATE:
+			if (populatedFromDateTimeValue) {
+				if ((year == 0) && (month == 0) && (day == 0)) {
+					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+							.equals(conn.getZeroDateTimeBehavior())) {
+
+						return null;
+					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+							.equals(conn.getZeroDateTimeBehavior())) {
+						throw new SQLException(
+								"Value '0000-00-00' can not be represented as java.sql.Date",
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					}
+
+					year = 1;
+					month = 1;
+					day = 1;
+				}
+
+				return rs
+						.fastDateCreate(
+								rs.getCalendarInstanceForSessionOrNew(), year,
+								month, day);
+			}
+
+			return rs.getNativeDateViaParseConversion(columnIndex + 1);
+		case Types.TIMESTAMP:
+			if (populatedFromDateTimeValue) {
+				if ((year == 0) && (month == 0) && (day == 0)) {
+					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+							.equals(conn.getZeroDateTimeBehavior())) {
+
+						return null;
+					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+							.equals(conn.getZeroDateTimeBehavior())) {
+						throw new SQLException(
+								"Value '0000-00-00' can not be represented as java.sql.Timestamp",
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					}
+
+					year = 1;
+					month = 1;
+					day = 1;
+				}
+
+				Timestamp ts = rs.fastTimestampCreate(rs
+						.getCalendarInstanceForSessionOrNew(), year, month,
+						day, hour, minute, seconds, nanos);
+
+				Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
+						sessionCalendar, targetCalendar, ts, conn
+								.getServerTimezoneTZ(), tz, rollForward);
+
+				return adjustedTs;
+			}
+
+			return rs.getNativeTimestampViaParseConversion(columnIndex + 1,
+					targetCalendar, tz, rollForward);
+
+		default:
+			throw new SQLException(
+					"Internal error - conversion method doesn't support this type",
+					SQLError.SQL_STATE_GENERAL_ERROR);
+		}
+	}
+
+	public abstract Object getNativeDateTimeValue(int columnIndex,
+			Calendar targetCalendar, int jdbcType, int mysqlType,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException;
+
+	protected double getNativeDouble(byte[] bits, int offset) {
+		long valueAsLong = (bits[offset + 0] & 0xff)
+				| ((long) (bits[offset + 1] & 0xff) << 8)
+				| ((long) (bits[offset + 2] & 0xff) << 16)
+				| ((long) (bits[offset + 3] & 0xff) << 24)
+				| ((long) (bits[offset + 4] & 0xff) << 32)
+				| ((long) (bits[offset + 5] & 0xff) << 40)
+				| ((long) (bits[offset + 6] & 0xff) << 48)
+				| ((long) (bits[offset + 7] & 0xff) << 56);
+
+		return Double.longBitsToDouble(valueAsLong);
+	}
+
+	public abstract double getNativeDouble(int columnIndex) throws SQLException;
+
+	protected float getNativeFloat(byte[] bits, int offset) {
+		int asInt = (bits[offset + 0] & 0xff)
+				| ((bits[offset + 1] & 0xff) << 8)
+				| ((bits[offset + 2] & 0xff) << 16)
+				| ((bits[offset + 3] & 0xff) << 24);
+
+		return Float.intBitsToFloat(asInt);
+	}
+
+	public abstract float getNativeFloat(int columnIndex) throws SQLException;
+
+	protected int getNativeInt(byte[] bits, int offset) {
+
+		int valueAsInt = (bits[offset + 0] & 0xff)
+				| ((bits[offset + 1] & 0xff) << 8)
+				| ((bits[offset + 2] & 0xff) << 16)
+				| ((bits[offset + 3] & 0xff) << 24);
+
+		return valueAsInt;
+	}
+
+	public abstract int getNativeInt(int columnIndex) throws SQLException;
+
+	protected long getNativeLong(byte[] bits, int offset) {
+		long valueAsLong = (bits[offset + 0] & 0xff)
+				| ((long) (bits[offset + 1] & 0xff) << 8)
+				| ((long) (bits[offset + 2] & 0xff) << 16)
+				| ((long) (bits[offset + 3] & 0xff) << 24)
+				| ((long) (bits[offset + 4] & 0xff) << 32)
+				| ((long) (bits[offset + 5] & 0xff) << 40)
+				| ((long) (bits[offset + 6] & 0xff) << 48)
+				| ((long) (bits[offset + 7] & 0xff) << 56);
+
+		return valueAsLong;
+	}
+
+	public abstract long getNativeLong(int columnIndex) throws SQLException;
+
+	protected short getNativeShort(byte[] bits, int offset) {
+		short asShort = (short) ((bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8));
+
+		return asShort;
+	}
+
+	public abstract short getNativeShort(int columnIndex) throws SQLException;
+
+	protected Time getNativeTime(int columnIndex, byte[] bits, int offset,
+			int length, Calendar targetCalendar, TimeZone tz,
+			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException {
+
+		int hour = 0;
+		int minute = 0;
+		int seconds = 0;
+
+		if (length != 0) {
+			// bits[0] // skip tm->neg
+			// binaryData.readLong(); // skip daysPart
+			hour = bits[offset + 5];
+			minute = bits[offset + 6];
+			seconds = bits[offset + 7];
+		}
+
+		Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();
+
+		synchronized (sessionCalendar) {
+			Time time = TimeUtil.fastTimeCreate(sessionCalendar, hour, minute,
+					seconds);
+
+			Time adjustedTime = TimeUtil.changeTimezone(conn, sessionCalendar,
+					targetCalendar, time, conn.getServerTimezoneTZ(), tz,
+					rollForward);
+
+			return adjustedTime;
+		}
+	}
+
+	public abstract Time getNativeTime(int columnIndex,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
+
+	protected Timestamp getNativeTimestamp(byte[] bits, int offset, int length,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
+		int year = 0;
+		int month = 0;
+		int day = 0;
+
+		int hour = 0;
+		int minute = 0;
+		int seconds = 0;
+
+		int nanos = 0;
+
+		if (length != 0) {
+			year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);
+			month = bits[2];
+			day = bits[3];
+
+			if (length > 4) {
+				hour = bits[offset + 4];
+				minute = bits[offset + 5];
+				seconds = bits[offset + 6];
+			}
+
+			if (length > 7) {
+				// MySQL uses microseconds
+				nanos = ((bits[offset + 7] & 0xff)
+						| ((bits[offset + 8] & 0xff) << 8)
+						| ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
+			}
+		}
+
+		if ((year == 0) && (month == 0) && (day == 0)) {
+			if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+					.equals(conn.getZeroDateTimeBehavior())) {
+
+				return null;
+			} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+					.equals(conn.getZeroDateTimeBehavior())) {
+				throw SQLError
+						.createSQLException(
+								"Value '0000-00-00' can not be represented as java.sql.Timestamp",
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+			}
+
+			year = 1;
+			month = 1;
+			day = 1;
+		}
+
+		Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
+				.getUtcCalendar()
+				: rs.getCalendarInstanceForSessionOrNew();
+
+		synchronized (sessionCalendar) {
+			Timestamp ts = rs.fastTimestampCreate(sessionCalendar, year, month,
+					day, hour, minute, seconds, nanos);
+
+			Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
+					sessionCalendar, targetCalendar, ts, conn
+							.getServerTimezoneTZ(), tz, rollForward);
+
+			return adjustedTs;
+		}
+	}
+
+	public abstract Timestamp getNativeTimestamp(int columnIndex,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
+
+	public abstract Reader getReader(int columnIndex) throws SQLException;
+
+	/**
+	 * Returns the value at the given column (index starts at 0) as a
+	 * java.lang.String with the requested encoding, using the given
+	 * ConnectionImpl to find character converters.
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to return.
+	 * @param encoding
+	 *            the Java name for the character encoding
+	 * @param conn
+	 *            the connection that created this result set row
+	 * 
+	 * @return the value for the given column (including NULL if it is) as a
+	 *         String
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs while retrieving the value.
+	 */
+	public abstract String getString(int index, String encoding,
+			ConnectionImpl conn) throws SQLException;
+
+	/**
+	 * Convenience method for turning a byte[] into a string with the given
+	 * encoding.
+	 * 
+	 * @param encoding
+	 *            the Java encoding name for the byte[] -> char conversion
+	 * @param conn
+	 *            the ConnectionImpl that created the result set
+	 * @param value
+	 *            the String value as a series of bytes, encoded using
+	 *            "encoding"
+	 * @param offset
+	 *            where to start the decoding
+	 * @param length
+	 *            how many bytes to decode
+	 * 
+	 * @return the String as decoded from bytes with the given encoding
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	protected String getString(String encoding, ConnectionImpl conn,
+			byte[] value, int offset, int length) throws SQLException {
+		String stringVal = null;
+
+		if ((conn != null) && conn.getUseUnicode()) {
+			try {
+				if (encoding == null) {
+					stringVal = new String(value);
+				} else {
+					SingleByteCharsetConverter converter = conn
+							.getCharsetConverter(encoding);
+
+					if (converter != null) {
+						stringVal = converter.toString(value, offset, length);
+					} else {
+						stringVal = new String(value, offset, length, encoding);
+					}
+				}
+			} catch (java.io.UnsupportedEncodingException E) {
+				throw SQLError
+						.createSQLException(
+								Messages
+										.getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
+										+ encoding + "'.", "0S100");
+			}
+		} else {
+			stringVal = StringUtils.toAsciiString(value, offset, length);
+		}
+
+		return stringVal;
+	}
+
+	protected Time getTimeFast(int columnIndex, byte[] timeAsBytes, int offset,
+			int length, Calendar targetCalendar, TimeZone tz,
+			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
+			throws SQLException {
+
+		int hr = 0;
+		int min = 0;
+		int sec = 0;
+
+		try {
+
+			if (timeAsBytes == null) {
+				return null;
+			}
+
+			boolean allZeroTime = true;
+			boolean onlyTimePresent = false;
+
+			for (int i = 0; i < length; i++) {
+				if (timeAsBytes[offset + i] == ':') {
+					onlyTimePresent = true;
+					break;
+				}
+			}
+
+			for (int i = 0; i < length; i++) {
+				byte b = timeAsBytes[offset + i];
+
+				if (b == ' ' || b == '-' || b == '/') {
+					onlyTimePresent = false;
+				}
+
+				if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/'
+						&& b != '.') {
+					allZeroTime = false;
+
+					break;
+				}
+			}
+
+			if (!onlyTimePresent && allZeroTime) {
+				if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+						.equals(conn.getZeroDateTimeBehavior())) {
+					return null;
+				} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+						.equals(conn.getZeroDateTimeBehavior())) {
+					throw SQLError.createSQLException("Value '"
+							+ new String(timeAsBytes)
+							+ "' can not be represented as java.sql.Time",
+							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				}
+
+				// We're left with the case of 'round' to a time Java _can_
+				// represent, which is '00:00:00'
+				return rs.fastTimeCreate(null, 0, 0, 0);
+			}
+
+			Field timeColField = this.metadata[columnIndex];
+
+			if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
+
+				switch (length) {
+				case 19: { // YYYY-MM-DD hh:mm:ss
+
+					hr = StringUtils.getInt(timeAsBytes, offset + length - 8,
+							offset + length - 6);
+					min = StringUtils.getInt(timeAsBytes, offset + length - 5,
+							offset + length - 3);
+					sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
+							offset + length);
+				}
+
+					break;
+				case 14:
+				case 12: {
+					hr = StringUtils.getInt(timeAsBytes, offset + length - 6,
+							offset + length - 4);
+					min = StringUtils.getInt(timeAsBytes, offset + length - 4,
+							offset + length - 2);
+					sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
+							offset + length);
+				}
+
+					break;
+
+				case 10: {
+					hr = StringUtils
+							.getInt(timeAsBytes, offset + 6, offset + 8);
+					min = StringUtils.getInt(timeAsBytes, offset + 8,
+							offset + 10);
+					sec = 0;
+				}
+
+					break;
+
+				default:
+					throw SQLError
+							.createSQLException(
+									Messages
+											.getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
+											+ (columnIndex + 1)
+											+ "("
+											+ timeColField + ").",
+									SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				} /* endswitch */
+
+				SQLWarning precisionLost = new SQLWarning(
+						Messages
+								.getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
+								+ columnIndex + "(" + timeColField + ").");
+				/*
+				 * if (this.warningChain == null) { this.warningChain =
+				 * precisionLost; } else {
+				 * this.warningChain.setNextWarning(precisionLost); }
+				 */
+			} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
+				hr = StringUtils.getInt(timeAsBytes, offset + 11, offset + 13);
+				min = StringUtils.getInt(timeAsBytes, offset + 14, offset + 16);
+				sec = StringUtils.getInt(timeAsBytes, offset + 17, offset + 19);
+
+				SQLWarning precisionLost = new SQLWarning(
+						Messages
+								.getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
+								+ (columnIndex + 1) + "(" + timeColField + ").");
+
+				/*
+				 * if (this.warningChain == null) { this.warningChain =
+				 * precisionLost; } else {
+				 * this.warningChain.setNextWarning(precisionLost); }
+				 */
+			} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
+				return rs.fastTimeCreate(null, 0, 0, 0); // midnight on the
+				// given
+				// date
+			} else {
+				// convert a String to a Time
+				if ((length != 5) && (length != 8)) {
+					throw SQLError.createSQLException(Messages
+							.getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
+							+ new String(timeAsBytes)
+							+ Messages.getString("ResultSet.___in_column__268")
+							+ (columnIndex + 1),
+							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+				}
+
+				hr = StringUtils.getInt(timeAsBytes, offset + 0, offset + 2);
+				min = StringUtils.getInt(timeAsBytes, offset + 3, offset + 5);
+				sec = (length == 5) ? 0 : StringUtils.getInt(timeAsBytes,
+						offset + 6, offset + 8);
+			}
+
+			Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();
+
+			synchronized (sessionCalendar) {
+				return TimeUtil.changeTimezone(conn, sessionCalendar,
+						targetCalendar, rs.fastTimeCreate(sessionCalendar, hr,
+								min, sec), conn.getServerTimezoneTZ(), tz,
+						rollForward);
+			}
+		} catch (Exception ex) {
+			throw SQLError.createSQLException(ex.toString(),
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+	}
+
+	public abstract Time getTimeFast(int columnIndex, Calendar targetCalendar,
+			TimeZone tz, boolean rollForward, ConnectionImpl conn,
+			ResultSetImpl rs) throws SQLException;
+
+	protected Timestamp getTimestampFast(int columnIndex,
+			byte[] timestampAsBytes, int offset, int length,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
+
+		try {
+			Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
+					.getUtcCalendar()
+					: rs.getCalendarInstanceForSessionOrNew();
+
+			synchronized (sessionCalendar) {
+				boolean allZeroTimestamp = true;
+
+				boolean onlyTimePresent = false;
+
+				for (int i = 0; i < length; i++) {
+					if (timestampAsBytes[offset + i] == ':') {
+						onlyTimePresent = true;
+						break;
+					}
+				}
+
+				for (int i = 0; i < length; i++) {
+					byte b = timestampAsBytes[offset + i];
+
+					if (b == ' ' || b == '-' || b == '/') {
+						onlyTimePresent = false;
+					}
+
+					if (b != '0' && b != ' ' && b != ':' && b != '-'
+							&& b != '/' && b != '.') {
+						allZeroTimestamp = false;
+
+						break;
+					}
+				}
+
+				if (!onlyTimePresent && allZeroTimestamp) {
+
+					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
+							.equals(conn.getZeroDateTimeBehavior())) {
+
+						return null;
+					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
+							.equals(conn.getZeroDateTimeBehavior())) {
+						throw SQLError
+								.createSQLException(
+										"Value '"
+												+ timestampAsBytes
+												+ "' can not be represented as java.sql.Timestamp",
+										SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					}
+
+					// We're left with the case of 'round' to a date Java _can_
+					// represent, which is '0001-01-01'.
+					return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
+
+				} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
+
+					return TimeUtil.changeTimezone(conn, sessionCalendar,
+							targetCalendar, rs.fastTimestampCreate(
+									sessionCalendar, StringUtils.getInt(
+											timestampAsBytes, offset, 4), 1, 1,
+									0, 0, 0, 0), conn.getServerTimezoneTZ(),
+							tz, rollForward);
+
+				} else {
+					if (timestampAsBytes[offset + length - 1] == '.') {
+						length--;
+					}
+
+					// Convert from TIMESTAMP or DATE
+					switch (length) {
+					case 26:
+					case 25:
+					case 24:
+					case 23:
+					case 22:
+					case 21:
+					case 20:
+					case 19: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 4);
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 5, offset + 7);
+						int day = StringUtils.getInt(timestampAsBytes,
+								offset + 8, offset + 10);
+						int hour = StringUtils.getInt(timestampAsBytes,
+								offset + 11, offset + 13);
+						int minutes = StringUtils.getInt(timestampAsBytes,
+								offset + 14, offset + 16);
+						int seconds = StringUtils.getInt(timestampAsBytes,
+								offset + 17, offset + 19);
+
+						int nanos = 0;
+
+						if (length > 19) {
+							int decimalIndex = -1;
+
+							for (int i = 0; i < length; i++) {
+								if (timestampAsBytes[offset + i] == '.') {
+									decimalIndex = i;
+								}
+							}
+
+							if (decimalIndex != -1) {
+								if ((decimalIndex + 2) <= length) {
+									nanos = StringUtils.getInt(
+											timestampAsBytes, decimalIndex + 1,
+											offset + length);
+								} else {
+									throw new IllegalArgumentException(); // re-thrown
+									// further
+									// down
+									// with
+									// a
+									// much better error message
+								}
+							}
+						}
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												sessionCalendar, year, month,
+												day, hour, minutes, seconds,
+												nanos), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 14: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 4);
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 4, offset + 6);
+						int day = StringUtils.getInt(timestampAsBytes,
+								offset + 6, offset + 8);
+						int hour = StringUtils.getInt(timestampAsBytes,
+								offset + 8, offset + 10);
+						int minutes = StringUtils.getInt(timestampAsBytes,
+								offset + 10, offset + 12);
+						int seconds = StringUtils.getInt(timestampAsBytes,
+								offset + 12, offset + 14);
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar,
+										rs.fastTimestampCreate(sessionCalendar,
+												year, month, day, hour,
+												minutes, seconds, 0), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 12: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 2);
+
+						if (year <= 69) {
+							year = (year + 100);
+						}
+
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 2, offset + 4);
+						int day = StringUtils.getInt(timestampAsBytes,
+								offset + 4, offset + 6);
+						int hour = StringUtils.getInt(timestampAsBytes,
+								offset + 6, offset + 8);
+						int minutes = StringUtils.getInt(timestampAsBytes,
+								offset + 8, offset + 10);
+						int seconds = StringUtils.getInt(timestampAsBytes,
+								offset + 10, offset + 12);
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												sessionCalendar, year + 1900,
+												month, day, hour, minutes,
+												seconds, 0), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 10: {
+						int year;
+						int month;
+						int day;
+						int hour;
+						int minutes;
+
+						boolean hasDash = false;
+
+						for (int i = 0; i < length; i++) {
+							if (timestampAsBytes[offset + i] == '-') {
+								hasDash = true;
+								break;
+							}
+						}
+
+						if ((this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
+								|| hasDash) {
+							year = StringUtils.getInt(timestampAsBytes,
+									offset + 0, offset + 4);
+							month = StringUtils.getInt(timestampAsBytes,
+									offset + 5, offset + 7);
+							day = StringUtils.getInt(timestampAsBytes,
+									offset + 8, offset + 10);
+							hour = 0;
+							minutes = 0;
+						} else {
+							year = StringUtils.getInt(timestampAsBytes,
+									offset + 0, offset + 2);
+
+							if (year <= 69) {
+								year = (year + 100);
+							}
+
+							month = StringUtils.getInt(timestampAsBytes,
+									offset + 2, offset + 4);
+							day = StringUtils.getInt(timestampAsBytes,
+									offset + 4, offset + 6);
+							hour = StringUtils.getInt(timestampAsBytes,
+									offset + 6, offset + 8);
+							minutes = StringUtils.getInt(timestampAsBytes,
+									offset + 8, offset + 10);
+
+							year += 1900; // two-digit year
+						}
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												sessionCalendar, year, month,
+												day, hour, minutes, 0, 0), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 8: {
+						boolean hasColon = false;
+
+						for (int i = 0; i < length; i++) {
+							if (timestampAsBytes[offset + i] == ':') {
+								hasColon = true;
+								break;
+							}
+						}
+
+						if (hasColon) {
+							int hour = StringUtils.getInt(timestampAsBytes,
+									offset + 0, offset + 2);
+							int minutes = StringUtils.getInt(timestampAsBytes,
+									offset + 3, offset + 5);
+							int seconds = StringUtils.getInt(timestampAsBytes,
+									offset + 6, offset + 8);
+
+							return TimeUtil.changeTimezone(conn,
+									sessionCalendar, targetCalendar, rs
+											.fastTimestampCreate(
+													sessionCalendar, 1970, 1,
+													1, hour, minutes, seconds,
+													0), conn
+											.getServerTimezoneTZ(), tz,
+									rollForward);
+
+						}
+
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 4);
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 4, offset + 6);
+						int day = StringUtils.getInt(timestampAsBytes,
+								offset + 6, offset + 8);
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												sessionCalendar, year - 1900,
+												month - 1, day, 0, 0, 0, 0),
+										conn.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 6: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 2);
+
+						if (year <= 69) {
+							year = (year + 100);
+						}
+
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 2, offset + 4);
+						int day = StringUtils.getInt(timestampAsBytes,
+								offset + 4, offset + 6);
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												sessionCalendar, year + 1900,
+												month, day, 0, 0, 0, 0), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					case 4: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 2);
+
+						if (year <= 69) {
+							year = (year + 100);
+						}
+
+						int month = StringUtils.getInt(timestampAsBytes,
+								offset + 2, offset + 4);
+
+						return TimeUtil.changeTimezone(conn, sessionCalendar,
+								targetCalendar, rs.fastTimestampCreate(
+										sessionCalendar, year + 1900, month, 1,
+										0, 0, 0, 0),
+								conn.getServerTimezoneTZ(), tz, rollForward);
+					}
+
+					case 2: {
+						int year = StringUtils.getInt(timestampAsBytes,
+								offset + 0, offset + 2);
+
+						if (year <= 69) {
+							year = (year + 100);
+						}
+
+						return TimeUtil
+								.changeTimezone(conn, sessionCalendar,
+										targetCalendar, rs.fastTimestampCreate(
+												null, year + 1900, 1, 1, 0, 0,
+												0, 0), conn
+												.getServerTimezoneTZ(), tz,
+										rollForward);
+					}
+
+					default:
+						throw new java.sql.SQLException(
+								"Bad format for Timestamp '"
+										+ new String(timestampAsBytes)
+										+ "' in column " + (columnIndex + 1)
+										+ ".",
+								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+					}
+				}
+			}
+		} catch (Exception e) {
+			throw new java.sql.SQLException("Cannot convert value '"
+					+ getString(columnIndex, "ISO8859_1", conn)
+					+ "' from column " + (columnIndex + 1) + " to TIMESTAMP.",
+					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
+		}
+	}
+
+	public abstract Timestamp getTimestampFast(int columnIndex,
+			Calendar targetCalendar, TimeZone tz, boolean rollForward,
+			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
+
+	/**
+	 * Could the column value at the given index (which starts at 0) be
+	 * interpreted as a floating-point number (has +/-/E/e in it)?
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to check.
+	 * 
+	 * @return true if the column value at the given index looks like it might
+	 *         be a floating-point number, false if not.
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public abstract boolean isFloatingPointNumber(int index)
+			throws SQLException;
+
+	/**
+	 * Is the column value at the given index (which starts at 0) NULL?
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) to check.
+	 * 
+	 * @return true if the column value is NULL, false if not.
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs
+	 */
+	public abstract boolean isNull(int index) throws SQLException;
+
+	/**
+	 * Returns the length of the column at the given index (which starts at 0).
+	 * 
+	 * @param index
+	 *            of the column value (starting at 0) for which to return the
+	 *            length.
+	 * @return the length of the requested column, 0 if null (clients of this
+	 *         interface should use isNull() beforehand to determine status of
+	 *         NULL values in the column).
+	 * 
+	 * @throws SQLException
+	 */
+	public abstract long length(int index) throws SQLException;
+
+	/**
+	 * Sets the given column value (only works currently with
+	 * ByteArrayRowHolder).
+	 * 
+	 * @param index
+	 *            index of the column value (starting at 0) to set.
+	 * @param value
+	 *            the (raw) value to set
+	 * 
+	 * @throws SQLException
+	 *             if an error occurs, or the concrete RowHolder doesn't support
+	 *             this operation.
+	 */
+	public abstract void setColumnValue(int index, byte[] value)
+			throws SQLException;
+
+	public void setMetadata(Field[] f) throws SQLException {
+		this.metadata = f;
+	}
+}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowData.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowData.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowData.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -49,7 +49,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	void addRow(RowHolder row) throws SQLException;
+	void addRow(ResultSetRow row) throws SQLException;
 
 	/**
 	 * Moves to after last.
@@ -92,7 +92,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	RowHolder getAt(int index) throws SQLException;
+	ResultSetRow getAt(int index) throws SQLException;
 
 	/**
 	 * Returns the current position in the result set as a row number.
@@ -191,7 +191,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	RowHolder next() throws SQLException;
+	ResultSetRow next() throws SQLException;
 
 	/**
 	 * Removes the row at the given index.

Copied: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataCursor.java (from rev 6449, branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java)
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/CursorRowProvider.java	2007-06-14 16:11:19 UTC (rev 6449)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataCursor.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -0,0 +1,476 @@
+/*
+ Copyright (C) 2002-2006 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of version 2 of the GNU General Public License as 
+ published by the Free Software Foundation.
+
+ There are special exceptions to the terms and conditions of the GPL 
+ as it is applied to this software. View the full text of the 
+ exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
+ software distribution.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+package com.mysql.jdbc;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Model for result set data backed by a cursor. Only works for forward-only
+ * result sets (but still works with updatable concurrency).
+ * 
+ * @version $Id: CursorRowProvider.java,v 1.1.2.1 2005/05/19 18:31:49 mmatthews
+ *          Exp $
+ */
+public class RowDataCursor implements RowData {
+
+	private final static int BEFORE_START_OF_ROWS = -1;
+
+	/**
+	 * The cache of rows we have retrieved from the server.
+	 */
+	private List fetchedRows;
+
+	/**
+	 * Where we are positionaly in the entire result set, used mostly to
+	 * facilitate easy 'isBeforeFirst()' and 'isFirst()' methods.
+	 */
+	private int currentPositionInEntireResult = BEFORE_START_OF_ROWS;
+
+	/**
+	 * Position in cache of rows, used to determine if we need to fetch more
+	 * rows from the server to satisfy a request for the next row.
+	 */
+	private int currentPositionInFetchedRows = BEFORE_START_OF_ROWS;
+
+	/**
+	 * The result set that we 'belong' to.
+	 */
+	private ResultSetImpl owner;
+
+	/**
+	 * Have we been told from the server that we have seen the last row?
+	 */
+	private boolean lastRowFetched = false;
+
+	/**
+	 * Field-level metadata from the server. We need this, because it is not
+	 * sent for each batch of rows, but we need the metadata to unpack the
+	 * results for each field.
+	 */
+	private Field[] metadata;
+
+	/**
+	 * Communications channel to the server
+	 */
+	private MysqlIO mysql;
+
+	/**
+	 * Identifier for the statement that created this cursor.
+	 */
+	private long statementIdOnServer;
+
+	/**
+	 * The prepared statement that created this cursor.
+	 */
+	private ServerPreparedStatement prepStmt;
+
+	/**
+	 * The server status for 'last-row-sent'...This might belong in mysqldefs,
+	 * but it it only ever referenced from here.
+	 */
+	private static final int SERVER_STATUS_LAST_ROW_SENT = 128;
+
+	/**
+	 * Have we attempted to fetch any rows yet?
+	 */
+	private boolean firstFetchCompleted = false;
+
+	private boolean wasEmpty = false;
+
+	/**
+	 * Creates a new cursor-backed row provider.
+	 * 
+	 * @param ioChannel
+	 *            connection to the server.
+	 * @param creatingStatement
+	 *            statement that opened the cursor.
+	 * @param metadata
+	 *            field-level metadata for the results that this cursor covers.
+	 */
+	public RowDataCursor(MysqlIO ioChannel,
+			ServerPreparedStatement creatingStatement, Field[] metadata) {
+		this.currentPositionInEntireResult = BEFORE_START_OF_ROWS;
+		this.metadata = metadata;
+		this.mysql = ioChannel;
+		this.statementIdOnServer = creatingStatement.getServerStatementId();
+		this.prepStmt = creatingStatement;
+	}
+
+	/**
+	 * Returns true if we got the last element.
+	 * 
+	 * @return DOCUMENT ME!
+	 */
+	public boolean isAfterLast() {
+		return lastRowFetched
+				&& this.currentPositionInFetchedRows > this.fetchedRows.size();
+	}
+
+	/**
+	 * Only works on non dynamic result sets.
+	 * 
+	 * @param index
+	 *            row number to get at
+	 * @return row data at index
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public ResultSetRow getAt(int ind) throws SQLException {
+		notSupported();
+
+		return null;
+	}
+
+	/**
+	 * Returns if iteration has not occured yet.
+	 * 
+	 * @return true if before first row
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public boolean isBeforeFirst() throws SQLException {
+		return this.currentPositionInEntireResult < 0;
+	}
+
+	/**
+	 * Moves the current position in the result set to the given row number.
+	 * 
+	 * @param rowNumber
+	 *            row to move to
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void setCurrentRow(int rowNumber) throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Returns the current position in the result set as a row number.
+	 * 
+	 * @return the current row number
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public int getCurrentRowNumber() throws SQLException {
+		return this.currentPositionInEntireResult + 1;
+	}
+
+	/**
+	 * Returns true if the result set is dynamic.
+	 * 
+	 * This means that move back and move forward won't work because we do not
+	 * hold on to the records.
+	 * 
+	 * @return true if this result set is streaming from the server
+	 */
+	public boolean isDynamic() {
+		return true;
+	}
+
+	/**
+	 * Has no records.
+	 * 
+	 * @return true if no records
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public boolean isEmpty() throws SQLException {
+		return this.isBeforeFirst() && this.isAfterLast();
+	}
+
+	/**
+	 * Are we on the first row of the result set?
+	 * 
+	 * @return true if on first row
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public boolean isFirst() throws SQLException {
+		return this.currentPositionInEntireResult == 0;
+	}
+
+	/**
+	 * Are we on the last row of the result set?
+	 * 
+	 * @return true if on last row
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public boolean isLast() throws SQLException {
+		return this.lastRowFetched
+				&& this.currentPositionInFetchedRows == (this.fetchedRows
+						.size() - 1);
+	}
+
+	/**
+	 * Adds a row to this row data.
+	 * 
+	 * @param row
+	 *            the row to add
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void addRow(ResultSetRow row) throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Moves to after last.
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void afterLast() throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Moves to before first.
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void beforeFirst() throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Moves to before last so next el is the last el.
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void beforeLast() throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * We're done.
+	 * 
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void close() throws SQLException {
+
+		this.metadata = null;
+		this.owner = null;
+	}
+
+	/**
+	 * Returns true if another row exists.
+	 * 
+	 * @return true if more rows
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public boolean hasNext() throws SQLException {
+
+		if (this.fetchedRows != null && this.fetchedRows.size() == 0) {
+			return false;
+		}
+
+		if (this.owner != null && this.owner.owningStatement != null) {
+			int maxRows = this.owner.owningStatement.maxRows;
+			
+			if (maxRows != -1 && this.currentPositionInEntireResult + 1 > maxRows) {
+				return false;
+			}	
+		}
+		
+		if (this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) {
+			// Case, we've fetched some rows, but are not at end of fetched
+			// block
+			if (this.currentPositionInFetchedRows < (this.fetchedRows.size() - 1)) {
+				return true;
+			} else if (this.currentPositionInFetchedRows == this.fetchedRows
+					.size()
+					&& this.lastRowFetched) {
+				return false;
+			} else {
+				// need to fetch to determine
+				fetchMoreRows();
+
+				return (this.fetchedRows.size() > 0);
+			}
+		}
+
+		// Okay, no rows _yet_, so fetch 'em
+
+		fetchMoreRows();
+
+		return this.fetchedRows.size() > 0;
+	}
+
+	/**
+	 * Moves the current position relative 'rows' from the current position.
+	 * 
+	 * @param rows
+	 *            the relative number of rows to move
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void moveRowRelative(int rows) throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Returns the next row.
+	 * 
+	 * @return the next row value
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public ResultSetRow next() throws SQLException {
+		if (this.fetchedRows == null && this.currentPositionInEntireResult != BEFORE_START_OF_ROWS) {
+			throw SQLError.createSQLException(
+					Messages
+							.getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
+					SQLError.SQL_STATE_GENERAL_ERROR);
+		}
+		
+		if (!hasNext()) {
+			return null;
+		}
+		
+		this.currentPositionInEntireResult++;
+		this.currentPositionInFetchedRows++;
+
+		// Catch the forced scroll-passed-end
+		if (this.fetchedRows != null && this.fetchedRows.size() == 0) {
+			return null;
+		}
+
+		if (this.currentPositionInFetchedRows > (this.fetchedRows.size() - 1)) {
+			fetchMoreRows();
+			this.currentPositionInFetchedRows = 0;
+		}
+
+		ResultSetRow row = (ResultSetRow) this.fetchedRows
+				.get(this.currentPositionInFetchedRows);
+
+		row.setMetadata(this.metadata);
+		
+		return row;
+	}
+
+	/**
+	 * 
+	 */
+	private void fetchMoreRows() throws SQLException {
+		if (this.lastRowFetched) {
+			this.fetchedRows = new ArrayList(0);
+			return;
+		}
+
+		synchronized (this.owner.connection.getMutex()) {
+			boolean oldFirstFetchCompleted = this.firstFetchCompleted;
+			
+			if (!this.firstFetchCompleted) {
+				this.firstFetchCompleted = true;
+			}
+
+			int numRowsToFetch = this.owner.getFetchSize();
+
+			if (numRowsToFetch == 0) {
+				numRowsToFetch = this.prepStmt.getFetchSize();
+			}
+			
+			if (numRowsToFetch == Integer.MIN_VALUE) {
+				// Handle the case where the user used 'old'
+				// streaming result sets
+
+				numRowsToFetch = 1;
+			}
+
+			this.fetchedRows = this.mysql.fetchRowsViaCursor(this.fetchedRows,
+					this.statementIdOnServer, this.metadata, numRowsToFetch);
+			this.currentPositionInFetchedRows = BEFORE_START_OF_ROWS;
+
+			if ((this.mysql.getServerStatus() & SERVER_STATUS_LAST_ROW_SENT) != 0) {
+				this.lastRowFetched = true;
+				
+				if (!oldFirstFetchCompleted && this.fetchedRows.size() == 0) {
+					this.wasEmpty  = true;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Removes the row at the given index.
+	 * 
+	 * @param index
+	 *            the row to move to
+	 * @throws SQLException
+	 *             if a database error occurs
+	 */
+	public void removeRow(int ind) throws SQLException {
+		notSupported();
+	}
+
+	/**
+	 * Only works on non dynamic result sets.
+	 * 
+	 * @return the size of this row data
+	 */
+	public int size() {
+		return RESULT_SET_SIZE_UNKNOWN;
+	}
+
+	private void nextRecord() throws SQLException {
+
+	}
+
+	private void notSupported() throws SQLException {
+		throw new OperationNotSupportedException();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.mysql.jdbc.RowProvider#setOwner(com.mysql.jdbc.ResultSet)
+	 */
+	public void setOwner(ResultSetImpl rs) {
+		this.owner = rs;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.mysql.jdbc.RowProvider#getOwner()
+	 */
+	public ResultSetInternalMethods getOwner() {
+		return this.owner;
+	}
+
+	public boolean wasEmpty() {
+		return this.wasEmpty;
+	}
+	
+	public void setMetadata(Field[] metadata) {
+		this.metadata = metadata;
+	}
+
+}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataDynamic.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataDynamic.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataDynamic.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -58,7 +58,7 @@
 
 	private boolean isBinaryEncoded = false;
 
-	private RowHolder nextRow;
+	private ResultSetRow nextRow;
 
 	private ResultSetImpl owner;
 
@@ -97,7 +97,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	public void addRow(RowHolder row) throws SQLException {
+	public void addRow(ResultSetRow row) throws SQLException {
 		notSupported();
 	}
 
@@ -243,7 +243,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	public RowHolder getAt(int ind) throws SQLException {
+	public ResultSetRow getAt(int ind) throws SQLException {
 		notSupported();
 
 		return null;
@@ -379,7 +379,7 @@
 	 * @throws SQLException
 	 *             if a database error occurs
 	 */
-	public RowHolder next() throws SQLException {
+	public ResultSetRow next() throws SQLException {
 		
 
 		nextRecord();
@@ -402,8 +402,7 @@
 	private void nextRecord() throws SQLException {
 
 		try {
-			if (!this.isAtEnd) {
-
+			if (!this.isAtEnd) {				
 				this.nextRow = this.io.nextRow(this.fields, this.columnCount,
 						this.isBinaryEncoded,
 						java.sql.ResultSet.CONCUR_READ_ONLY, true, true, null);

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataKeyset.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataKeyset.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataKeyset.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -44,7 +44,7 @@
 		return canonicalSql.substring(whereClausePos);
 	}
 
-	public void addRow(RowHolder row) throws SQLException {
+	public void addRow(ResultSetRow row) throws SQLException {
 		// TODO Auto-generated method stub
 
 	}
@@ -82,7 +82,7 @@
 		}
 	}
 
-	public RowHolder getAt(int index) throws SQLException {
+	public ResultSetRow getAt(int index) throws SQLException {
 		// TODO Auto-generated method stub
 		return null;
 	}
@@ -137,7 +137,7 @@
 
 	}
 
-	public RowHolder next() throws SQLException {
+	public ResultSetRow next() throws SQLException {
 		// TODO Auto-generated method stub
 		return null;
 	}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataStatic.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataStatic.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowDataStatic.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -60,7 +60,7 @@
 	 * @param row
 	 *            DOCUMENT ME!
 	 */
-	public void addRow(RowHolder row) {
+	public void addRow(ResultSetRow row) {
 		this.rows.add(row);
 	}
 
@@ -99,12 +99,12 @@
 	 * 
 	 * @return DOCUMENT ME!
 	 */
-	public RowHolder getAt(int atIndex) {
+	public ResultSetRow getAt(int atIndex) {
 		if ((atIndex < 0) || (atIndex >= this.rows.size())) {
 			return null;
 		}
 
-		return (RowHolder) this.rows.get(atIndex);
+		return (ResultSetRow) this.rows.get(atIndex);
 	}
 
 	/**
@@ -211,11 +211,11 @@
 	 * 
 	 * @return DOCUMENT ME!
 	 */
-	public RowHolder next() throws SQLException {
+	public ResultSetRow next() throws SQLException {
 		this.index++;
 
 		if (this.index < this.rows.size()) {
-			RowHolder row = (RowHolder) this.rows.get(this.index);
+			ResultSetRow row = (ResultSetRow) this.rows.get(this.index);
 			row.setMetadata(this.metadata);
 			
 			return row; 

Deleted: branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/RowHolder.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1,1356 +0,0 @@
-/*
- Copyright (C) 2007 MySQL AB
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as 
- published by the Free Software Foundation.
-
- There are special exceptions to the terms and conditions of the GPL 
- as it is applied to this software. View the full text of the 
- exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
- software distribution.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- 
- */
-package com.mysql.jdbc;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.sql.Date;
-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.StringTokenizer;
-import java.util.TimeZone;
-
-/**
- * Classes that implement this interface represent one row of data from the
- * MySQL server that might be stored in different ways depending on whether the
- * result set was streaming (so they wrap a reusable packet), or whether the
- * result set was cached or via a server-side cursor (so they represent a
- * byte[][]).
- * 
- * Notice that <strong>no</strong> bounds checking is expected for implementors
- * of this interface, it happens in ResultSetImpl.
- * 
- * @version $Id: $
- */
-public abstract class RowHolder {
-	/**
-	 * The metadata of the fields of this result set.
-	 */
-	protected Field[] metadata;
-
-	public abstract void closeOpenStreams();
-
-	public abstract InputStream getBinaryInputStream(int columnIndex)
-			throws SQLException;
-
-	/**
-	 * Returns the value at the given column (index starts at 0) "raw" (i.e.
-	 * as-returned by the server).
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to return.
-	 * @return the value for the given column (including NULL if it is)
-	 * @throws SQLException
-	 *             if an error occurs while retrieving the value.
-	 */
-	public abstract byte[] getColumnValue(int index) throws SQLException;
-
-	protected final java.sql.Date getDateFast(int columnIndex,
-			byte[] dateAsBytes, int offset, int length, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-
-		int year = 0;
-		int month = 0;
-		int day = 0;
-
-		try {
-			if (dateAsBytes == null) {
-				return null;
-			}
-
-			boolean allZeroDate = true;
-
-			boolean onlyTimePresent = false;
-
-			for (int i = 0; i < length; i++) {
-				if (dateAsBytes[offset + i] == ':') {
-					onlyTimePresent = true;
-					break;
-				}
-			}
-
-			for (int i = 0; i < length; i++) {
-				byte b = dateAsBytes[offset + i];
-
-				if (b == ' ' || b == '-' || b == '/') {
-					onlyTimePresent = false;
-				}
-
-				if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/'
-						&& b != '.') {
-					allZeroDate = false;
-
-					break;
-				}
-			}
-
-			if (!onlyTimePresent && allZeroDate) {
-
-				if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-						.equals(conn.getZeroDateTimeBehavior())) {
-
-					return null;
-				} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-						.equals(conn.getZeroDateTimeBehavior())) {
-					throw SQLError.createSQLException("Value '"
-							+ new String(dateAsBytes)
-							+ "' can not be represented as java.sql.Date",
-							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-				}
-
-				// We're left with the case of 'round' to a date Java _can_
-				// represent, which is '0001-01-01'.
-				return rs.fastDateCreate(null, 1, 1, 1);
-
-			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
-				// Convert from TIMESTAMP
-				switch (length) {
-				case 21:
-				case 19: { // java.sql.Timestamp format
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 4);
-					month = StringUtils.getInt(dateAsBytes, offset + 5,
-							offset + 7);
-					day = StringUtils.getInt(dateAsBytes, offset + 8,
-							offset + 10);
-
-					return rs.fastDateCreate(null, year, month, day);
-				}
-
-				case 14:
-				case 8: {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 4);
-					month = StringUtils.getInt(dateAsBytes, offset + 4,
-							offset + 6);
-					day = StringUtils.getInt(dateAsBytes, offset + 6,
-							offset + 8);
-
-					return rs.fastDateCreate(null, year, month, day);
-				}
-
-				case 12:
-				case 10:
-				case 6: {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 2);
-
-					if (year <= 69) {
-						year = year + 100;
-					}
-
-					month = StringUtils.getInt(dateAsBytes, offset + 2,
-							offset + 4);
-					day = StringUtils.getInt(dateAsBytes, offset + 4,
-							offset + 6);
-
-					return rs.fastDateCreate(null, year + 1900, month, day);
-				}
-
-				case 4: {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 4);
-
-					if (year <= 69) {
-						year = year + 100;
-					}
-
-					month = StringUtils.getInt(dateAsBytes, offset + 2,
-							offset + 4);
-
-					return rs.fastDateCreate(null, year + 1900, month, 1);
-				}
-
-				case 2: {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 2);
-
-					if (year <= 69) {
-						year = year + 100;
-					}
-
-					return rs.fastDateCreate(null, year + 1900, 1, 1);
-				}
-
-				default:
-					throw SQLError
-							.createSQLException(
-									Messages
-											.getString(
-													"ResultSet.Bad_format_for_Date",
-													new Object[] {
-															new String(
-																	dateAsBytes),
-															Constants
-																	.integerValueOf(columnIndex + 1) }),
-									SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
-				} /* endswitch */
-			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
-
-				if (length == 2 || length == 1) {
-					year = StringUtils.getInt(dateAsBytes, offset, offset
-							+ length);
-
-					if (year <= 69) {
-						year = year + 100;
-					}
-
-					year += 1900;
-				} else {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 4);
-				}
-
-				return rs.fastDateCreate(null, year, 1, 1);
-			} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
-				return rs.fastDateCreate(null, 1970, 1, 1); // Return EPOCH
-			} else {
-				if (length < 10) {
-					if (length == 8) {
-						return rs.fastDateCreate(null, 1970, 1, 1); // Return
-						// EPOCH for
-						// TIME
-					}
-
-					throw SQLError
-							.createSQLException(
-									Messages
-											.getString(
-													"ResultSet.Bad_format_for_Date",
-													new Object[] {
-															new String(
-																	dateAsBytes),
-															Constants
-																	.integerValueOf(columnIndex + 1) }),
-									SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
-				}
-
-				if (length != 18) {
-					year = StringUtils.getInt(dateAsBytes, offset + 0,
-							offset + 4);
-					month = StringUtils.getInt(dateAsBytes, offset + 5,
-							offset + 7);
-					day = StringUtils.getInt(dateAsBytes, offset + 8,
-							offset + 10);
-				} else {
-					// JDK-1.3 timestamp format, not real easy to parse
-					// positionally :p
-					StringTokenizer st = new StringTokenizer(new String(
-							dateAsBytes, offset, length, "ISO8859_1"), "- ");
-
-					year = Integer.parseInt(st.nextToken());
-					month = Integer.parseInt(st.nextToken());
-					day = Integer.parseInt(st.nextToken());
-				}
-			}
-
-			return rs.fastDateCreate(null, year, month, day);
-		} catch (SQLException sqlEx) {
-			throw sqlEx; // don't re-wrap
-		} catch (Exception e) {
-			throw SQLError.createSQLException(Messages.getString(
-					"ResultSet.Bad_format_for_Date", new Object[] {
-							new String(dateAsBytes),
-							Constants.integerValueOf(columnIndex + 1) }),
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
-		}
-	}
-
-	public abstract java.sql.Date getDateFast(int columnIndex,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
-
-	/**
-	 * Returns the value at the given column (index starts at 0) as an int. *
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to return.
-	 * @return the value for the given column (returns 0 if NULL, use isNull()
-	 *         to determine if the value was actually NULL)
-	 * @throws SQLException
-	 *             if an error occurs while retrieving the value.
-	 */
-	public abstract int getInt(int columnIndex) throws SQLException;
-
-	/**
-	 * Returns the value at the given column (index starts at 0) as a long. *
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to return.
-	 * @return the value for the given column (returns 0 if NULL, use isNull()
-	 *         to determine if the value was actually NULL)
-	 * @throws SQLException
-	 *             if an error occurs while retrieving the value.
-	 */
-	public abstract long getLong(int columnIndex) throws SQLException;
-
-	protected java.sql.Date getNativeDate(int columnIndex, byte[] bits,
-			int offset, int length, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException {
-
-		int year = 0;
-		int month = 0;
-		int day = 0;
-
-		if (length != 0) {
-			year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);
-
-			month = bits[offset + 2];
-			day = bits[offset + 3];
-		}
-
-		if ((year == 0) && (month == 0) && (day == 0)) {
-			if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-					.equals(conn.getZeroDateTimeBehavior())) {
-				return null;
-			} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-					.equals(conn.getZeroDateTimeBehavior())) {
-				throw SQLError
-						.createSQLException(
-								"Value '0000-00-00' can not be represented as java.sql.Date",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-			}
-
-			year = 1;
-			month = 1;
-			day = 1;
-		}
-
-		return rs.fastDateCreate(rs.getCalendarInstanceForSessionOrNew(), year,
-				month, day);
-	}
-
-	public abstract Date getNativeDate(int columnIndex, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException;
-
-	protected Object getNativeDateTimeValue(int columnIndex, byte[] bits,
-			int offset, int length, Calendar targetCalendar, int jdbcType,
-			int mysqlType, TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException {
-
-		int year = 0;
-		int month = 0;
-		int day = 0;
-
-		int hour = 0;
-		int minute = 0;
-		int seconds = 0;
-
-		int nanos = 0;
-
-		if (bits == null) {
-
-			return null;
-		}
-
-		Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
-				.getUtcCalendar()
-				: rs.getCalendarInstanceForSessionOrNew();
-
-		boolean populatedFromDateTimeValue = false;
-
-		switch (mysqlType) {
-		case MysqlDefs.FIELD_TYPE_DATETIME:
-		case MysqlDefs.FIELD_TYPE_TIMESTAMP:
-			populatedFromDateTimeValue = true;
-
-			if (length != 0) {
-				year = (bits[offset + 0] & 0xff)
-						| ((bits[offset + 1] & 0xff) << 8);
-				month = bits[offset + 2];
-				day = bits[offset + 3];
-
-				if (length > 4) {
-					hour = bits[offset + 4];
-					minute = bits[offset + 5];
-					seconds = bits[offset + 6];
-				}
-
-				if (length > 7) {
-					// MySQL uses microseconds
-					nanos = ((bits[offset + 7] & 0xff)
-							| ((bits[offset + 8] & 0xff) << 8)
-							| ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
-				}
-			}
-
-			break;
-		case MysqlDefs.FIELD_TYPE_DATE:
-			populatedFromDateTimeValue = true;
-
-			if (bits.length != 0) {
-				year = (bits[offset + 0] & 0xff)
-						| ((bits[offset + 1] & 0xff) << 8);
-				month = bits[offset + 2];
-				day = bits[offset + 3];
-			}
-
-			break;
-		case MysqlDefs.FIELD_TYPE_TIME:
-			populatedFromDateTimeValue = true;
-
-			if (bits.length != 0) {
-				// bits[0] // skip tm->neg
-				// binaryData.readLong(); // skip daysPart
-				hour = bits[offset + 5];
-				minute = bits[offset + 6];
-				seconds = bits[offset + 7];
-			}
-
-			year = 1970;
-			month = 1;
-			day = 1;
-
-			break;
-		default:
-			populatedFromDateTimeValue = false;
-		}
-
-		switch (jdbcType) {
-		case Types.TIME:
-			if (populatedFromDateTimeValue) {
-				Time time = TimeUtil.fastTimeCreate(rs
-						.getCalendarInstanceForSessionOrNew(), hour, minute,
-						seconds);
-
-				Time adjustedTime = TimeUtil.changeTimezone(conn,
-						sessionCalendar, targetCalendar, time, conn
-								.getServerTimezoneTZ(), tz, rollForward);
-
-				return adjustedTime;
-			}
-
-			return rs.getNativeTimeViaParseConversion(columnIndex + 1,
-					targetCalendar, tz, rollForward);
-
-		case Types.DATE:
-			if (populatedFromDateTimeValue) {
-				if ((year == 0) && (month == 0) && (day == 0)) {
-					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-							.equals(conn.getZeroDateTimeBehavior())) {
-
-						return null;
-					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-							.equals(conn.getZeroDateTimeBehavior())) {
-						throw new SQLException(
-								"Value '0000-00-00' can not be represented as java.sql.Date",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-					}
-
-					year = 1;
-					month = 1;
-					day = 1;
-				}
-
-				return rs
-						.fastDateCreate(
-								rs.getCalendarInstanceForSessionOrNew(), year,
-								month, day);
-			}
-
-			return rs.getNativeDateViaParseConversion(columnIndex + 1);
-		case Types.TIMESTAMP:
-			if (populatedFromDateTimeValue) {
-				if ((year == 0) && (month == 0) && (day == 0)) {
-					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-							.equals(conn.getZeroDateTimeBehavior())) {
-
-						return null;
-					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-							.equals(conn.getZeroDateTimeBehavior())) {
-						throw new SQLException(
-								"Value '0000-00-00' can not be represented as java.sql.Timestamp",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-					}
-
-					year = 1;
-					month = 1;
-					day = 1;
-				}
-
-				Timestamp ts = rs.fastTimestampCreate(rs
-						.getCalendarInstanceForSessionOrNew(), year, month,
-						day, hour, minute, seconds, nanos);
-
-				Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
-						sessionCalendar, targetCalendar, ts, conn
-								.getServerTimezoneTZ(), tz, rollForward);
-
-				return adjustedTs;
-			}
-
-			return rs.getNativeTimestampViaParseConversion(columnIndex + 1,
-					targetCalendar, tz, rollForward);
-
-		default:
-			throw new SQLException(
-					"Internal error - conversion method doesn't support this type",
-					SQLError.SQL_STATE_GENERAL_ERROR);
-		}
-	}
-
-	public abstract Object getNativeDateTimeValue(int columnIndex,
-			Calendar targetCalendar, int jdbcType, int mysqlType,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException;
-
-	protected double getNativeDouble(byte[] bits, int offset) {
-		long valueAsLong = (bits[offset + 0] & 0xff)
-				| ((long) (bits[offset + 1] & 0xff) << 8)
-				| ((long) (bits[offset + 2] & 0xff) << 16)
-				| ((long) (bits[offset + 3] & 0xff) << 24)
-				| ((long) (bits[offset + 4] & 0xff) << 32)
-				| ((long) (bits[offset + 5] & 0xff) << 40)
-				| ((long) (bits[offset + 6] & 0xff) << 48)
-				| ((long) (bits[offset + 7] & 0xff) << 56);
-
-		return Double.longBitsToDouble(valueAsLong);
-	}
-
-	public abstract double getNativeDouble(int columnIndex) throws SQLException;
-
-	protected float getNativeFloat(byte[] bits, int offset) {
-		int asInt = (bits[offset + 0] & 0xff)
-				| ((bits[offset + 1] & 0xff) << 8)
-				| ((bits[offset + 2] & 0xff) << 16)
-				| ((bits[offset + 3] & 0xff) << 24);
-
-		return Float.intBitsToFloat(asInt);
-	}
-
-	public abstract float getNativeFloat(int columnIndex) throws SQLException;
-
-	protected int getNativeInt(byte[] bits, int offset) {
-
-		int valueAsInt = (bits[offset + 0] & 0xff)
-				| ((bits[offset + 1] & 0xff) << 8)
-				| ((bits[offset + 2] & 0xff) << 16)
-				| ((bits[offset + 3] & 0xff) << 24);
-
-		return valueAsInt;
-	}
-
-	public abstract int getNativeInt(int columnIndex) throws SQLException;
-
-	protected long getNativeLong(byte[] bits, int offset) {
-		long valueAsLong = (bits[offset + 0] & 0xff)
-				| ((long) (bits[offset + 1] & 0xff) << 8)
-				| ((long) (bits[offset + 2] & 0xff) << 16)
-				| ((long) (bits[offset + 3] & 0xff) << 24)
-				| ((long) (bits[offset + 4] & 0xff) << 32)
-				| ((long) (bits[offset + 5] & 0xff) << 40)
-				| ((long) (bits[offset + 6] & 0xff) << 48)
-				| ((long) (bits[offset + 7] & 0xff) << 56);
-
-		return valueAsLong;
-	}
-
-	public abstract long getNativeLong(int columnIndex) throws SQLException;
-
-	protected short getNativeShort(byte[] bits, int offset) {
-		short asShort = (short) ((bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8));
-
-		return asShort;
-	}
-
-	public abstract short getNativeShort(int columnIndex) throws SQLException;
-
-	protected Time getNativeTime(int columnIndex, byte[] bits, int offset,
-			int length, Calendar targetCalendar, TimeZone tz,
-			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException {
-
-		int hour = 0;
-		int minute = 0;
-		int seconds = 0;
-
-		if (length != 0) {
-			// bits[0] // skip tm->neg
-			// binaryData.readLong(); // skip daysPart
-			hour = bits[offset + 5];
-			minute = bits[offset + 6];
-			seconds = bits[offset + 7];
-		}
-
-		Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();
-
-		synchronized (sessionCalendar) {
-			Time time = TimeUtil.fastTimeCreate(sessionCalendar, hour, minute,
-					seconds);
-
-			Time adjustedTime = TimeUtil.changeTimezone(conn, sessionCalendar,
-					targetCalendar, time, conn.getServerTimezoneTZ(), tz,
-					rollForward);
-
-			return adjustedTime;
-		}
-	}
-
-	public abstract Time getNativeTime(int columnIndex,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
-
-	protected Timestamp getNativeTimestamp(byte[] bits, int offset, int length,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
-		int year = 0;
-		int month = 0;
-		int day = 0;
-
-		int hour = 0;
-		int minute = 0;
-		int seconds = 0;
-
-		int nanos = 0;
-
-		if (length != 0) {
-			year = (bits[offset + 0] & 0xff) | ((bits[offset + 1] & 0xff) << 8);
-			month = bits[2];
-			day = bits[3];
-
-			if (length > 4) {
-				hour = bits[offset + 4];
-				minute = bits[offset + 5];
-				seconds = bits[offset + 6];
-			}
-
-			if (length > 7) {
-				// MySQL uses microseconds
-				nanos = ((bits[offset + 7] & 0xff)
-						| ((bits[offset + 8] & 0xff) << 8)
-						| ((bits[offset + 9] & 0xff) << 16) | ((bits[offset + 10] & 0xff) << 24)) * 1000;
-			}
-		}
-
-		if ((year == 0) && (month == 0) && (day == 0)) {
-			if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-					.equals(conn.getZeroDateTimeBehavior())) {
-
-				return null;
-			} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-					.equals(conn.getZeroDateTimeBehavior())) {
-				throw SQLError
-						.createSQLException(
-								"Value '0000-00-00' can not be represented as java.sql.Timestamp",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-			}
-
-			year = 1;
-			month = 1;
-			day = 1;
-		}
-
-		Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
-				.getUtcCalendar()
-				: rs.getCalendarInstanceForSessionOrNew();
-
-		synchronized (sessionCalendar) {
-			Timestamp ts = rs.fastTimestampCreate(sessionCalendar, year, month,
-					day, hour, minute, seconds, nanos);
-
-			Timestamp adjustedTs = TimeUtil.changeTimezone(conn,
-					sessionCalendar, targetCalendar, ts, conn
-							.getServerTimezoneTZ(), tz, rollForward);
-
-			return adjustedTs;
-		}
-	}
-
-	public abstract Timestamp getNativeTimestamp(int columnIndex,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
-
-	public abstract Reader getReader(int columnIndex) throws SQLException;
-
-	/**
-	 * Returns the value at the given column (index starts at 0) as a
-	 * java.lang.String with the requested encoding, using the given
-	 * ConnectionImpl to find character converters.
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to return.
-	 * @param encoding
-	 *            the Java name for the character encoding
-	 * @param conn
-	 *            the connection that created this result set row
-	 * 
-	 * @return the value for the given column (including NULL if it is) as a
-	 *         String
-	 * 
-	 * @throws SQLException
-	 *             if an error occurs while retrieving the value.
-	 */
-	public abstract String getString(int index, String encoding,
-			ConnectionImpl conn) throws SQLException;
-
-	/**
-	 * Convenience method for turning a byte[] into a string with the given
-	 * encoding.
-	 * 
-	 * @param encoding
-	 *            the Java encoding name for the byte[] -> char conversion
-	 * @param conn
-	 *            the ConnectionImpl that created the result set
-	 * @param value
-	 *            the String value as a series of bytes, encoded using
-	 *            "encoding"
-	 * @param offset
-	 *            where to start the decoding
-	 * @param length
-	 *            how many bytes to decode
-	 * 
-	 * @return the String as decoded from bytes with the given encoding
-	 * 
-	 * @throws SQLException
-	 *             if an error occurs
-	 */
-	protected String getString(String encoding, ConnectionImpl conn,
-			byte[] value, int offset, int length) throws SQLException {
-		String stringVal = null;
-
-		if ((conn != null) && conn.getUseUnicode()) {
-			try {
-				if (encoding == null) {
-					stringVal = new String(value);
-				} else {
-					SingleByteCharsetConverter converter = conn
-							.getCharsetConverter(encoding);
-
-					if (converter != null) {
-						stringVal = converter.toString(value, offset, length);
-					} else {
-						stringVal = new String(value, offset, length, encoding);
-					}
-				}
-			} catch (java.io.UnsupportedEncodingException E) {
-				throw SQLError
-						.createSQLException(
-								Messages
-										.getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
-										+ encoding + "'.", "0S100");
-			}
-		} else {
-			stringVal = StringUtils.toAsciiString(value, offset, length);
-		}
-
-		return stringVal;
-	}
-
-	protected Time getTimeFast(int columnIndex, byte[] timeAsBytes, int offset,
-			int length, Calendar targetCalendar, TimeZone tz,
-			boolean rollForward, ConnectionImpl conn, ResultSetImpl rs)
-			throws SQLException {
-
-		int hr = 0;
-		int min = 0;
-		int sec = 0;
-
-		try {
-
-			if (timeAsBytes == null) {
-				return null;
-			}
-
-			boolean allZeroTime = true;
-			boolean onlyTimePresent = false;
-
-			for (int i = 0; i < length; i++) {
-				if (timeAsBytes[offset + i] == ':') {
-					onlyTimePresent = true;
-					break;
-				}
-			}
-
-			for (int i = 0; i < length; i++) {
-				byte b = timeAsBytes[offset + i];
-
-				if (b == ' ' || b == '-' || b == '/') {
-					onlyTimePresent = false;
-				}
-
-				if (b != '0' && b != ' ' && b != ':' && b != '-' && b != '/'
-						&& b != '.') {
-					allZeroTime = false;
-
-					break;
-				}
-			}
-
-			if (!onlyTimePresent && allZeroTime) {
-				if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-						.equals(conn.getZeroDateTimeBehavior())) {
-					return null;
-				} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-						.equals(conn.getZeroDateTimeBehavior())) {
-					throw SQLError.createSQLException("Value '"
-							+ new String(timeAsBytes)
-							+ "' can not be represented as java.sql.Time",
-							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-				}
-
-				// We're left with the case of 'round' to a time Java _can_
-				// represent, which is '00:00:00'
-				return rs.fastTimeCreate(null, 0, 0, 0);
-			}
-
-			Field timeColField = this.metadata[columnIndex];
-
-			if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
-
-				switch (length) {
-				case 19: { // YYYY-MM-DD hh:mm:ss
-
-					hr = StringUtils.getInt(timeAsBytes, offset + length - 8,
-							offset + length - 6);
-					min = StringUtils.getInt(timeAsBytes, offset + length - 5,
-							offset + length - 3);
-					sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
-							offset + length);
-				}
-
-					break;
-				case 14:
-				case 12: {
-					hr = StringUtils.getInt(timeAsBytes, offset + length - 6,
-							offset + length - 4);
-					min = StringUtils.getInt(timeAsBytes, offset + length - 4,
-							offset + length - 2);
-					sec = StringUtils.getInt(timeAsBytes, offset + length - 2,
-							offset + length);
-				}
-
-					break;
-
-				case 10: {
-					hr = StringUtils
-							.getInt(timeAsBytes, offset + 6, offset + 8);
-					min = StringUtils.getInt(timeAsBytes, offset + 8,
-							offset + 10);
-					sec = 0;
-				}
-
-					break;
-
-				default:
-					throw SQLError
-							.createSQLException(
-									Messages
-											.getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
-											+ (columnIndex + 1)
-											+ "("
-											+ timeColField + ").",
-									SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-				} /* endswitch */
-
-				SQLWarning precisionLost = new SQLWarning(
-						Messages
-								.getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
-								+ columnIndex + "(" + timeColField + ").");
-				/*
-				 * if (this.warningChain == null) { this.warningChain =
-				 * precisionLost; } else {
-				 * this.warningChain.setNextWarning(precisionLost); }
-				 */
-			} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
-				hr = StringUtils.getInt(timeAsBytes, offset + 11, offset + 13);
-				min = StringUtils.getInt(timeAsBytes, offset + 14, offset + 16);
-				sec = StringUtils.getInt(timeAsBytes, offset + 17, offset + 19);
-
-				SQLWarning precisionLost = new SQLWarning(
-						Messages
-								.getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
-								+ (columnIndex + 1) + "(" + timeColField + ").");
-
-				/*
-				 * if (this.warningChain == null) { this.warningChain =
-				 * precisionLost; } else {
-				 * this.warningChain.setNextWarning(precisionLost); }
-				 */
-			} else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
-				return rs.fastTimeCreate(null, 0, 0, 0); // midnight on the
-				// given
-				// date
-			} else {
-				// convert a String to a Time
-				if ((length != 5) && (length != 8)) {
-					throw SQLError.createSQLException(Messages
-							.getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
-							+ new String(timeAsBytes)
-							+ Messages.getString("ResultSet.___in_column__268")
-							+ (columnIndex + 1),
-							SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-				}
-
-				hr = StringUtils.getInt(timeAsBytes, offset + 0, offset + 2);
-				min = StringUtils.getInt(timeAsBytes, offset + 3, offset + 5);
-				sec = (length == 5) ? 0 : StringUtils.getInt(timeAsBytes,
-						offset + 6, offset + 8);
-			}
-
-			Calendar sessionCalendar = rs.getCalendarInstanceForSessionOrNew();
-
-			synchronized (sessionCalendar) {
-				return TimeUtil.changeTimezone(conn, sessionCalendar,
-						targetCalendar, rs.fastTimeCreate(sessionCalendar, hr,
-								min, sec), conn.getServerTimezoneTZ(), tz,
-						rollForward);
-			}
-		} catch (Exception ex) {
-			throw SQLError.createSQLException(ex.toString(),
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-		}
-	}
-
-	public abstract Time getTimeFast(int columnIndex, Calendar targetCalendar,
-			TimeZone tz, boolean rollForward, ConnectionImpl conn,
-			ResultSetImpl rs) throws SQLException;
-
-	protected Timestamp getTimestampFast(int columnIndex,
-			byte[] timestampAsBytes, int offset, int length,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException {
-
-		try {
-			Calendar sessionCalendar = conn.getUseJDBCCompliantTimezoneShift() ? conn
-					.getUtcCalendar()
-					: rs.getCalendarInstanceForSessionOrNew();
-
-			synchronized (sessionCalendar) {
-				boolean allZeroTimestamp = true;
-
-				boolean onlyTimePresent = false;
-
-				for (int i = 0; i < length; i++) {
-					if (timestampAsBytes[offset + i] == ':') {
-						onlyTimePresent = true;
-						break;
-					}
-				}
-
-				for (int i = 0; i < length; i++) {
-					byte b = timestampAsBytes[offset + i];
-
-					if (b == ' ' || b == '-' || b == '/') {
-						onlyTimePresent = false;
-					}
-
-					if (b != '0' && b != ' ' && b != ':' && b != '-'
-							&& b != '/' && b != '.') {
-						allZeroTimestamp = false;
-
-						break;
-					}
-				}
-
-				if (!onlyTimePresent && allZeroTimestamp) {
-
-					if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
-							.equals(conn.getZeroDateTimeBehavior())) {
-
-						return null;
-					} else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
-							.equals(conn.getZeroDateTimeBehavior())) {
-						throw SQLError
-								.createSQLException(
-										"Value '"
-												+ timestampAsBytes
-												+ "' can not be represented as java.sql.Timestamp",
-										SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-					}
-
-					// We're left with the case of 'round' to a date Java _can_
-					// represent, which is '0001-01-01'.
-					return rs.fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
-
-				} else if (this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
-
-					return TimeUtil.changeTimezone(conn, sessionCalendar,
-							targetCalendar, rs.fastTimestampCreate(
-									sessionCalendar, StringUtils.getInt(
-											timestampAsBytes, offset, 4), 1, 1,
-									0, 0, 0, 0), conn.getServerTimezoneTZ(),
-							tz, rollForward);
-
-				} else {
-					if (timestampAsBytes[offset + length - 1] == '.') {
-						length--;
-					}
-
-					// Convert from TIMESTAMP or DATE
-					switch (length) {
-					case 26:
-					case 25:
-					case 24:
-					case 23:
-					case 22:
-					case 21:
-					case 20:
-					case 19: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 4);
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 5, offset + 7);
-						int day = StringUtils.getInt(timestampAsBytes,
-								offset + 8, offset + 10);
-						int hour = StringUtils.getInt(timestampAsBytes,
-								offset + 11, offset + 13);
-						int minutes = StringUtils.getInt(timestampAsBytes,
-								offset + 14, offset + 16);
-						int seconds = StringUtils.getInt(timestampAsBytes,
-								offset + 17, offset + 19);
-
-						int nanos = 0;
-
-						if (length > 19) {
-							int decimalIndex = -1;
-
-							for (int i = 0; i < length; i++) {
-								if (timestampAsBytes[offset + i] == '.') {
-									decimalIndex = i;
-								}
-							}
-
-							if (decimalIndex != -1) {
-								if ((decimalIndex + 2) <= length) {
-									nanos = StringUtils.getInt(
-											timestampAsBytes, decimalIndex + 1,
-											offset + length);
-								} else {
-									throw new IllegalArgumentException(); // re-thrown
-									// further
-									// down
-									// with
-									// a
-									// much better error message
-								}
-							}
-						}
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												sessionCalendar, year, month,
-												day, hour, minutes, seconds,
-												nanos), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 14: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 4);
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 4, offset + 6);
-						int day = StringUtils.getInt(timestampAsBytes,
-								offset + 6, offset + 8);
-						int hour = StringUtils.getInt(timestampAsBytes,
-								offset + 8, offset + 10);
-						int minutes = StringUtils.getInt(timestampAsBytes,
-								offset + 10, offset + 12);
-						int seconds = StringUtils.getInt(timestampAsBytes,
-								offset + 12, offset + 14);
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar,
-										rs.fastTimestampCreate(sessionCalendar,
-												year, month, day, hour,
-												minutes, seconds, 0), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 12: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 2);
-
-						if (year <= 69) {
-							year = (year + 100);
-						}
-
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 2, offset + 4);
-						int day = StringUtils.getInt(timestampAsBytes,
-								offset + 4, offset + 6);
-						int hour = StringUtils.getInt(timestampAsBytes,
-								offset + 6, offset + 8);
-						int minutes = StringUtils.getInt(timestampAsBytes,
-								offset + 8, offset + 10);
-						int seconds = StringUtils.getInt(timestampAsBytes,
-								offset + 10, offset + 12);
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												sessionCalendar, year + 1900,
-												month, day, hour, minutes,
-												seconds, 0), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 10: {
-						int year;
-						int month;
-						int day;
-						int hour;
-						int minutes;
-
-						boolean hasDash = false;
-
-						for (int i = 0; i < length; i++) {
-							if (timestampAsBytes[offset + i] == '-') {
-								hasDash = true;
-								break;
-							}
-						}
-
-						if ((this.metadata[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
-								|| hasDash) {
-							year = StringUtils.getInt(timestampAsBytes,
-									offset + 0, offset + 4);
-							month = StringUtils.getInt(timestampAsBytes,
-									offset + 5, offset + 7);
-							day = StringUtils.getInt(timestampAsBytes,
-									offset + 8, offset + 10);
-							hour = 0;
-							minutes = 0;
-						} else {
-							year = StringUtils.getInt(timestampAsBytes,
-									offset + 0, offset + 2);
-
-							if (year <= 69) {
-								year = (year + 100);
-							}
-
-							month = StringUtils.getInt(timestampAsBytes,
-									offset + 2, offset + 4);
-							day = StringUtils.getInt(timestampAsBytes,
-									offset + 4, offset + 6);
-							hour = StringUtils.getInt(timestampAsBytes,
-									offset + 6, offset + 8);
-							minutes = StringUtils.getInt(timestampAsBytes,
-									offset + 8, offset + 10);
-
-							year += 1900; // two-digit year
-						}
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												sessionCalendar, year, month,
-												day, hour, minutes, 0, 0), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 8: {
-						boolean hasColon = false;
-
-						for (int i = 0; i < length; i++) {
-							if (timestampAsBytes[offset + i] == ':') {
-								hasColon = true;
-								break;
-							}
-						}
-
-						if (hasColon) {
-							int hour = StringUtils.getInt(timestampAsBytes,
-									offset + 0, offset + 2);
-							int minutes = StringUtils.getInt(timestampAsBytes,
-									offset + 3, offset + 5);
-							int seconds = StringUtils.getInt(timestampAsBytes,
-									offset + 6, offset + 8);
-
-							return TimeUtil.changeTimezone(conn,
-									sessionCalendar, targetCalendar, rs
-											.fastTimestampCreate(
-													sessionCalendar, 1970, 1,
-													1, hour, minutes, seconds,
-													0), conn
-											.getServerTimezoneTZ(), tz,
-									rollForward);
-
-						}
-
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 4);
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 4, offset + 6);
-						int day = StringUtils.getInt(timestampAsBytes,
-								offset + 6, offset + 8);
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												sessionCalendar, year - 1900,
-												month - 1, day, 0, 0, 0, 0),
-										conn.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 6: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 2);
-
-						if (year <= 69) {
-							year = (year + 100);
-						}
-
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 2, offset + 4);
-						int day = StringUtils.getInt(timestampAsBytes,
-								offset + 4, offset + 6);
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												sessionCalendar, year + 1900,
-												month, day, 0, 0, 0, 0), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					case 4: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 2);
-
-						if (year <= 69) {
-							year = (year + 100);
-						}
-
-						int month = StringUtils.getInt(timestampAsBytes,
-								offset + 2, offset + 4);
-
-						return TimeUtil.changeTimezone(conn, sessionCalendar,
-								targetCalendar, rs.fastTimestampCreate(
-										sessionCalendar, year + 1900, month, 1,
-										0, 0, 0, 0),
-								conn.getServerTimezoneTZ(), tz, rollForward);
-					}
-
-					case 2: {
-						int year = StringUtils.getInt(timestampAsBytes,
-								offset + 0, offset + 2);
-
-						if (year <= 69) {
-							year = (year + 100);
-						}
-
-						return TimeUtil
-								.changeTimezone(conn, sessionCalendar,
-										targetCalendar, rs.fastTimestampCreate(
-												null, year + 1900, 1, 1, 0, 0,
-												0, 0), conn
-												.getServerTimezoneTZ(), tz,
-										rollForward);
-					}
-
-					default:
-						throw new java.sql.SQLException(
-								"Bad format for Timestamp '"
-										+ new String(timestampAsBytes)
-										+ "' in column " + (columnIndex + 1)
-										+ ".",
-								SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-					}
-				}
-			}
-		} catch (Exception e) {
-			throw new java.sql.SQLException("Cannot convert value '"
-					+ getString(columnIndex, "ISO8859_1", conn)
-					+ "' from column " + (columnIndex + 1) + " to TIMESTAMP.",
-					SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
-		}
-	}
-
-	public abstract Timestamp getTimestampFast(int columnIndex,
-			Calendar targetCalendar, TimeZone tz, boolean rollForward,
-			ConnectionImpl conn, ResultSetImpl rs) throws SQLException;
-
-	/**
-	 * Could the column value at the given index (which starts at 0) be
-	 * interpreted as a floating-point number (has +/-/E/e in it)?
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to check.
-	 * 
-	 * @return true if the column value at the given index looks like it might
-	 *         be a floating-point number, false if not.
-	 * 
-	 * @throws SQLException
-	 *             if an error occurs
-	 */
-	public abstract boolean isFloatingPointNumber(int index)
-			throws SQLException;
-
-	/**
-	 * Is the column value at the given index (which starts at 0) NULL?
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) to check.
-	 * 
-	 * @return true if the column value is NULL, false if not.
-	 * 
-	 * @throws SQLException
-	 *             if an error occurs
-	 */
-	public abstract boolean isNull(int index) throws SQLException;
-
-	/**
-	 * Returns the length of the column at the given index (which starts at 0).
-	 * 
-	 * @param index
-	 *            of the column value (starting at 0) for which to return the
-	 *            length.
-	 * @return the length of the requested column, 0 if null (clients of this
-	 *         interface should use isNull() beforehand to determine status of
-	 *         NULL values in the column).
-	 * 
-	 * @throws SQLException
-	 */
-	public abstract long length(int index) throws SQLException;
-
-	/**
-	 * Sets the given column value (only works currently with
-	 * ByteArrayRowHolder).
-	 * 
-	 * @param index
-	 *            index of the column value (starting at 0) to set.
-	 * @param value
-	 *            the (raw) value to set
-	 * 
-	 * @throws SQLException
-	 *             if an error occurs, or the concrete RowHolder doesn't support
-	 *             this operation.
-	 */
-	public abstract void setColumnValue(int index, byte[] value)
-			throws SQLException;
-
-	public void setMetadata(Field[] f) throws SQLException {
-		this.metadata = f;
-	}
-}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/ServerPreparedStatement.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -696,7 +696,7 @@
 
 										while (rs.next()) {
 											this.batchedGeneratedKeys
-													.add(new ByteArrayRowHolder(new byte[][] { rs
+													.add(new ByteArrayRow(new byte[][] { rs
 															.getBytes(1) }));
 										}
 									} finally {

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/StatementImpl.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -1597,7 +1597,7 @@
 				for (int i = 0; i < numKeys; i++) {
 					byte[][] row = new byte[1][];
 					row[0] = Long.toString(beginAt++).getBytes();
-					rowSet.add(new ByteArrayRowHolder(row));
+					rowSet.add(new ByteArrayRow(row));
 				}
 			}
 		}

Modified: branches/branch_5_1/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java
===================================================================
--- branches/branch_5_1/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java	2007-06-15 01:10:23 UTC (rev 6450)
+++ branches/branch_5_1/connector-j/src/com/mysql/jdbc/UpdatableResultSet.java	2007-06-15 01:24:27 UTC (rev 6451)
@@ -85,7 +85,7 @@
 	private String refreshSQL = null;
 
 	/** The binary data for the 'current' row */
-	private RowHolder savedCurrentRow;
+	private ResultSetRow savedCurrentRow;
 
 	private String tableOnlyName;
 
@@ -780,11 +780,11 @@
 			}
 		}
 		
-		RowHolder rowHolder = new ByteArrayRowHolder(newRow);
+		ResultSetRow resultSetRow = new ByteArrayRow(newRow);
 		
-		refreshRow(this.inserter, rowHolder);
+		refreshRow(this.inserter, resultSetRow);
 		
-		this.rowData.addRow(rowHolder);
+		this.rowData.addRow(resultSetRow);
 		resetInserter();
 	}
 
@@ -947,7 +947,7 @@
 		this.doingUpdates = false;
 		this.savedCurrentRow = this.thisRow;
 		byte[][] newRowData = new byte[numFields][];
-		this.thisRow = new ByteArrayRowHolder(newRowData);
+		this.thisRow = new ByteArrayRow(newRowData);
 
 		for (int i = 0; i < numFields; i++) {
 			if (!this.populateInserterWithDefaultValues) {
@@ -1178,7 +1178,7 @@
 	}
 	
 	private synchronized void refreshRow(PreparedStatement updateInsertStmt, 
-			RowHolder rowToRefresh) throws SQLException {
+			ResultSetRow rowToRefresh) throws SQLException {
 		if (this.refresher == null) {
 			if (this.refreshSQL == null) {
 				generateStatements();

Thread
Connector/J commit: r6451 - branches/branch_5_1/connector-j/src/com/mysql/jdbcmmatthews15 Jun