Index: java/drda/org/apache/derby/impl/drda/DRDAResultSet.java
===================================================================
--- java/drda/org/apache/derby/impl/drda/DRDAResultSet.java	(revision 391391)
+++ java/drda/org/apache/derby/impl/drda/DRDAResultSet.java	(working copy)
@@ -439,7 +439,7 @@
 	 *  column; false otherwise.
 	 ****/
  
-	private boolean hasLobColumns()	throws SQLException
+	protected boolean hasLobColumns() throws SQLException
 	{
 		ResultSetMetaData rsmd = rs.getMetaData();
 		int ncols = rsmd.getColumnCount();
Index: java/drda/org/apache/derby/impl/drda/DRDAStatement.java
===================================================================
--- java/drda/org/apache/derby/impl/drda/DRDAStatement.java	(revision 391391)
+++ java/drda/org/apache/derby/impl/drda/DRDAStatement.java	(working copy)
@@ -323,13 +323,24 @@
 	
 
 	/**
-	 * Delegation method to call DRDAResultSet to set query 
-	 * options sent on OPNQRY.
+	 * Set query options sent on OPNQRY and pass options down to the
+	 * current <code>DRDAResultSet</code> object.
+	 *
+	 * @param blksize QRYBLKSZ (Query Block Size)
+	 * @param qryblkctl QRYBLKCTL (Query Block Protocol Control)
+	 * @param maxblkext MAXBLKEXT (Maximum Number of Extra Blocks)
+	 * @param outovropt OUTOVROPT (Output Override Option)
+	 * @param qryrowset QRYROWSET (Query Rowset Size)
+	 * @param qryclsimpl QRYCLSIMP (Query Close Implicit)
 	 * @see DRDAResultSet#setOPNQRYOptions(int, int, int, int, int, int)
 	 */
 	protected void setOPNQRYOptions(int blksize, int qryblkctl,
 								  int maxblkext, int outovropt,int qryrowset,int qryclsimpl)
 	{
+		this.qryrowset = qryrowset;
+		this.blksize = blksize;
+		this.maxblkext = maxblkext;
+		this.outovropt = outovropt;
 		currentDrdaRs.setOPNQRYOptions( blksize, qryblkctl, maxblkext, 
 				outovropt, qryrowset, qryclsimpl);
 	}
Index: java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
===================================================================
--- java/drda/org/apache/derby/impl/drda/DRDAConnThread.java	(revision 391391)
+++ java/drda/org/apache/derby/impl/drda/DRDAConnThread.java	(working copy)
@@ -575,6 +575,41 @@
 	}
 
 	/**
+	 * Cleans up and closes a statement if an exception is thrown when
+	 * collecting QRYDTA in response to OPNQRY or CNTQRY.
+	 *
+	 * @param stmt the DRDA statement to close
+	 * @param sqle the exception that was thrown
+	 * @param writerMark start index for the first DSS to clear from
+	 * the output buffer
+	 * @exception DRDAProtocolException if a DRDA protocol error is
+	 * detected
+	 */
+	private void cleanUpAndCloseStatement(DRDAStatement stmt,
+										  SQLException sqle,
+										  int writerMark)
+		throws DRDAProtocolException
+	{
+		if (stmt != null) {
+			writer.clearDSSesBackToMark(writerMark);
+			if (!stmt.rsIsClosed()) {
+				try {
+					stmt.rsClose();
+				} catch (SQLException ec) {
+					if (SanityManager.DEBUG) {
+						trace("Warning: Error closing statement");
+					}
+				}
+				writeABNUOWRM();
+				writeSQLCARD(sqle, CodePoint.SVRCOD_ERROR, 0, 0);
+			}
+		} else {
+			writeSQLCARDs(sqle, 0);
+		}
+		errorInChain(sqle);
+	}
+
+	/**
 	 * Process DRDA commands we can receive once server attributes have been
 	 * exchanged.
 	 *
@@ -602,7 +637,7 @@
 						stmt = parseCNTQRY();
 						if (stmt != null)
 						{
-							writeQRYDTA(stmt);
+							writeQRYDTA(stmt, false);
 							if (stmt.rsIsClosed())
 							{
 								writeENDQRYRM(CodePoint.SVRCOD_WARNING);
@@ -614,30 +649,9 @@
 					}
 					catch(SQLException e)
 					{
-						if (stmt != null)
- 						{
-							// if we got a SQLException we need to clean up and
- 							// close the statement Beetle 4758
-							writer.clearDSSesBackToMark(writerMark);
- 							if (! stmt.rsIsClosed())
- 							{
- 								try {
- 									stmt.rsClose();
- 								}
- 								catch (SQLException ec)
- 								{
- 									if (SanityManager.DEBUG)
- 										trace("Warning: Error closing statement");
-								}
-								writeABNUOWRM();
-								writeSQLCARD(e,CodePoint.SVRCOD_ERROR,0,0);
-							}
-						}
-						else 
-						{
-							writeSQLCARDs(e, 0);
-						}
-						errorInChain(e);
+						// if we got a SQLException we need to clean up and
+						// close the statement Beetle 4758
+						cleanUpAndCloseStatement(stmt, e, writerMark);
 					}
 					break;
 				case CodePoint.EXCSQLIMM:
@@ -737,11 +751,25 @@
 							checkWarning(null, ps, null, 0, false, true);
 
 							writeQRYDSC(stmt, false);
-							// We could send QRYDTA here if there's no LOB data
-							// in the result set, and if we are using LMTBLKPRC, as
-							// allowed by drda spec, as an option.
 
 							stmt.rsSuspend();
+
+							if (stmt.getQryprctyp() == CodePoint.LMTBLKPRC) {
+								// The DRDA spec allows us to send
+								// QRYDTA here if there are no LOB
+								// columns.
+								DRDAResultSet drdars =
+									stmt.getCurrentDrdaResultSet();
+								try {
+									if (drdars != null &&
+										!drdars.hasLobColumns()) {
+										writeQRYDTA(stmt, true);
+									}
+								} catch (SQLException sqle) {
+									cleanUpAndCloseStatement(stmt, sqle,
+															 writerMark);
+								}
+							}
 						}
 					}
 					catch (SQLException e)
@@ -3621,7 +3649,7 @@
 				writeQRYDSC(stmt, true);
 				writer.endDdm();
 				writer.startDdm(CodePoint.FDODTA);
-				writeFDODTA(stmt);
+				writeFDODTA(stmt, false);
 				writer.endDdm();
 				writer.endDdmAndDss();
 			}
@@ -3666,7 +3694,7 @@
 			 * to add "no lob columns".
 			 */
 			if (stmt.getQryprctyp() == CodePoint.LMTBLKPRC)
-				writeQRYDTA(stmt);
+				writeQRYDTA(stmt, false);
 		}
 		else  if (! sendSQLDTARD)
 		{
@@ -6006,10 +6034,12 @@
 	 *   Byte string
 	 *
 	 * @param stmt	DRDA statement we are processing
+	 * @param opnqry <code>true</code> if QRYDTA is written in the
+	 * reply to an OPNQRY command
 	 * @throws DRDAProtocolException
      * @throws SQLException
 	 */
-	private void writeQRYDTA (DRDAStatement stmt) 
+	private void writeQRYDTA (DRDAStatement stmt, boolean opnqry)
 		throws DRDAProtocolException, SQLException
 	{
 		boolean getMoreData = true;
@@ -6039,7 +6069,7 @@
 		while(getMoreData)
 		{			
 			sentExtData = false;
-			getMoreData = writeFDODTA(stmt);
+			getMoreData = writeFDODTA(stmt, opnqry);
 
 			if (stmt.getExtDtaObjects() != null &&
 					stmt.getSplitQRYDTA() == null)
@@ -6111,7 +6141,7 @@
 	 * - the outer "do ... while ... " loop processes a ROWSET, one row
 	 *   at a time. For non-ROWSET cursors, and for callable statements,
 	 *   this loop executes only once.
-	 * - the inner "for ... i < numCols ..." loop processes each column
+	 * - the inner "for ... i &lt; numCols ..." loop processes each column
 	 *   in the current row, or each output parmeter in the procedure.
 	 *
 	 * Most column data is written directly inline in the QRYDTA block.
@@ -6120,8 +6150,18 @@
 	 * Data Pointer is written into the QRYDTA block, and the actual
 	 * data flows in separate EXTDTA blocks which are returned
 	 * after this QRYDTA block.
+	 *
+	 * @param stmt DRDA statement we are processing
+	 * @param opnqry <code>true</code> if QRYDTA is written in the
+	 * reply to an OPNQRY command
+	 * @return <code>true</code> if more data could be written,
+	 * <code>false</code> if the block is full and should be sent
+	 * @exception DRDAProtocolException if a DRDA protocol error is
+	 * detected
+	 * @exception SQLException if an error occurs when invoking JDBC
+	 * methods
 	 */
-	private boolean writeFDODTA (DRDAStatement stmt) 
+	private boolean writeFDODTA (DRDAStatement stmt, boolean opnqry)
 		throws DRDAProtocolException, SQLException
 	{
 		boolean hasdata = false;
@@ -6140,7 +6180,10 @@
 		if (rs != null)
 		{
 			numCols = stmt.getNumRsCols();					
-			if (stmt.isScrollable())
+			// On OPNQRY we always start fetching from the
+			// beginning. On CNTQRY, if the cursor is scrollable, we
+			// need to position the cursor before fetching.
+			if (!opnqry && stmt.isScrollable())
 				hasdata = positionCursor(stmt, rs);
 			else
 				hasdata = rs.next();
@@ -6167,9 +6210,12 @@
 			else
 				writeSQLCAGRP(sqlw, sqlw.getErrorCode(), 1, -1);
 
-			// if we were asked not to return data, mark QRYDTA null; do not
-			// return yet, need to make rowCount right
-			boolean noRetrieveRS = (rs != null && !stmt.getQryrtndta());
+			// If we were asked not to return data (QRYRTNDTA), mark
+			// QRYDTA null. Do not return yet, we need to make
+			// rowCount right. We never get QRYRTNDTA in an OPNQRY
+			// command.
+			boolean noRetrieveRS =
+				!opnqry && rs != null && !stmt.getQryrtndta();
 			if (noRetrieveRS)
 				writer.writeByte(0xFF);  //QRYDTA null indicator: IS NULL
 			else
Index: java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/values1.inc
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/values1.inc	(revision 391391)
+++ java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/values1.inc	(working copy)
@@ -35,5 +35,12 @@
 endDdm
 endDss
 flush
-skipDss	//ignore OPNQRYRM
-skipDss	//ignore QRYDSC
+readReplyDss
+readLengthAndCodepoint OPNQRYRM
+skipBytes
+readReplyDss
+readLengthAndCodepoint QRYDSC
+skipBytes
+readReplyDss
+readLengthAndCodepoint QRYDTA
+skipBytes
Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/supersimple.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/supersimple.out	(revision 391391)
+++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNet/supersimple.out	(working copy)
@@ -149,12 +149,8 @@
 NoHoldForConnection;
 ij(CONNECTION1)> prepare s1 as 'select * from t';
 ij(CONNECTION1)> execute s1;
-I          
------
 ERROR 40XL1: A lock could not be obtained within the time requested
 ij(CONNECTION1)> execute s1;
-I          
------
 ERROR 40XL1: A lock could not be obtained within the time requested
 ij(CONNECTION1)> -- Bug 5967 - Selecting from 2 lob columns w/ the first one having data of length 0
 create table t1 (c1 clob(10), c2 clob(10));
Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/supersimple.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/supersimple.out	(revision 391391)
+++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/supersimple.out	(working copy)
@@ -149,12 +149,8 @@
 NoHoldForConnection;
 ij(CONNECTION1)> prepare s1 as 'select * from t';
 ij(CONNECTION1)> execute s1;
-I          
------
 ERROR 40XL1: A lock could not be obtained within the time requested
 ij(CONNECTION1)> execute s1;
-I          
------
 ERROR 40XL1: A lock could not be obtained within the time requested
 ij(CONNECTION1)> -- Bug 5967 - Selecting from 2 lob columns w/ the first one having data of length 0
 create table t1 (c1 clob(10), c2 clob(10));
Index: java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out
===================================================================
--- java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out	(revision 391391)
+++ java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/forupdate.out	(working copy)
@@ -43,7 +43,7 @@
 ----- with a 'cursor not updatable' message
 get cursor c as 'select i, v from t1, t2';
 ij> delete from t1 where current of c;
-ERROR 42X23: Cursor SQL_CURLH000C1 is not updatable.
+ERROR 42X30: Cursor 'SQL_CURLH000C1' not found. Verify that autocommit is OFF.
 ij> --  cursor with same name already exists
 get cursor c as 'select i, v from t1, t2';
 ERROR (no SQLState): Duplicate cursor names are not allowed.
@@ -62,13 +62,13 @@
 ----- we know because the delete is refused with a 'cursor not updatable' message
 get cursor c2 as 'select i, v from t1, t2 for read only';
 ij> delete from t1 where current of c2;
-ERROR 42X23: Cursor SQL_CURLH000C1 is not updatable.
+ERROR 42X30: Cursor 'SQL_CURLH000C1' not found. Verify that autocommit is OFF.
 ij> close c2;
 ij> -- . read only for updatable cursor spec
 ----- we know because the delete is refused with a 'cursor not updatable' message
 get cursor c3 as 'select i, v from t1 where i is not null for read only';
 ij> delete from t1 where current of c3;
-ERROR 42X23: Cursor SQL_CURLH000C1 is not updatable.
+ERROR 42X30: Cursor 'SQL_CURLH000C1' not found. Verify that autocommit is OFF.
 ij> close c3;
 ij> -- . for update col not in select list
 ----- this is allowed:
