You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2006/05/06 01:50:13 UTC

svn commit: r400212 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/functionTests/master/ testing/org/apache/derbyTesting/functionTests/suites/ testing/org/apache/derbyTesting/functionTests/test...

Author: kahatlen
Date: Fri May  5 16:50:12 2006
New Revision: 400212

URL: http://svn.apache.org/viewcvs?rev=400212&view=rev
Log:
DERBY-1277: Call to rs.isLast() may cause rs.getXXX() return values
from the last row instead of the current row in scrollable resultsets

In scrollable updatable resultset, a call to rs.isLast() may cause
rs.getXXX() return values from the last row, instead of for the
current row. It is caused by TableScanResultSet and EmbedResultSet
sharing DataValueColumn descriptors, and that the call to isLast()
will make TableScanResultSet modify the data.

Attaching a fix, where ScrollInsensitiveResultSet does not return
ExecRow from the source resultset, only from the hashtable. This
ensures that navigation in source resultsets do not affect the current
row of the scrollinsensitive resultset.

Also extended the test testRelative to test with concurrency mode
CONCUR_UPDATABLE, and fixed it so that it can run in derbynetclient
framework.

Patch contributed by Andreas Korneliussen.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/testRelative.out
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/testRelative.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java?rev=400212&r1=400211&r2=400212&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/execute/ScrollInsensitiveResultSet.java Fri May  5 16:50:12 2006
@@ -345,6 +345,9 @@
 					break;
 				}
 			}
+			if (result != null) {
+				result = getRowFromHashTable(row);
+			}
 			currentRow = result;
 			return result;
 		}
@@ -515,6 +518,9 @@
 			 * Get row from the source.
 			 */
 			result = getNextRowFromSource();
+			if (result !=null) {
+				result = getRowFromHashTable(currentPosition);
+			}
 		}
 		else if (currentPosition < positionInSource)
 		{
@@ -616,44 +622,37 @@
 	 */
 	public ExecRow	getLastRow()
 		throws StandardException
-	{
-		ExecRow result;
-
+	{		
 	    if ( ! isOpen ) 
 		{
 			throw StandardException.newException(SQLState.LANG_RESULT_SET_NOT_OPEN, "next");
 		}
-
-		/* Have we already seen the last row? */
-		if (seenLast)
+		
+		if (!seenLast) 
 		{
-			// Return null if the set was empty
-			if (lastPosition == 0)
-			{
-				currentRow = null;
-				return null;
-			}
-			else
+			attachStatementContext();
+
+			if (SanityManager.DEBUG)
 			{
-				return getRowFromHashTable(lastPosition);
-			}
+				if (!isTopResultSet)
+				{
+					SanityManager.THROWASSERT(
+											  this + "expected to be the top ResultSet");
+				}
+			}
+			
+			/* Scroll to the end, filling the hash table as
+			 * we scroll, and return the last row that we find.
+			 */
+			ExecRow result = null;
+			while ((result = getNextRowFromSource()) != null);
 		}
-
-		attachStatementContext();
-
-		if (SanityManager.DEBUG)
+		
+		if (SanityManager.DEBUG && !seenLast)
 		{
-			if (!isTopResultSet)
-			{
-				SanityManager.THROWASSERT(
-					this + "expected to be the top ResultSet");
-			}
+			SanityManager.THROWASSERT(this + "expected to have seen last");
 		}
-
-		/* Scroll to the end, filling the hash table as
-		 * we scroll, and return the last row that we find.
-		 */
-		while ((result = getNextRowFromSource()) != null);
+		
 		beforeFirst = false;
 		afterLast = false;
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/testRelative.out
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/testRelative.out?rev=400212&r1=400211&r2=400212&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/testRelative.out (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/testRelative.out Fri May  5 16:50:12 2006
@@ -1,8 +1,11 @@
 Test testRelative starting
-Value=work1
-isFirst=false isLast=false isAfterLast=false
-Value=work3
-Value=work1
-isFirst=false isLast=false isAfterLast=true
+Value = work1
+Value = work3
+isFirst = false isLast = false isAfterLast = false
+Value = work1
+PASS -- expected exception
+Value = work1
+Value = work3
+isFirst = false isLast = false isAfterLast = false
+Value = work1
 PASS -- expected exception
-SQLSTATE(24000): Invalid cursor state - no current row.

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude?rev=400212&r1=400211&r2=400212&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/suites/DerbyNetClient.exclude Fri May  5 16:50:12 2006
@@ -2,7 +2,6 @@
 # excluding scrollCursors2.java because updatable resultsets & scroll sensitive cursors are not supported
 # excluding batchUpdate.java for it hits a problem in networkserver ('beetle' 5561)
 # excluding statementJdbc20.java because this tests fetch_reverse throughout the test
-# excluding jdbcapi/testRelative.java because it is a new test that requires debugging with the IBM Driver
 # excluding jdbcapi/resultsetJdbc30.java because the features tested are not implemented by Derby Client
 # excluding jdbcapi/statementJdbc30.java - Client behaves differently. Need to look into this
 # excluding jdbcapi/dataSourceReference.java - client side only tests, tests all data sources
@@ -18,7 +17,6 @@
 #
 jdbcapi/batchUpdate.java
 jdbcapi/statementJdbc20.java
-jdbcapi/testRelative.java
 jdbcapi/resultsetJdbc30.java
 jdbcapi/statementJdbc30.java
 jdbcapi/dataSourceReference.java

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/testRelative.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/testRelative.java?rev=400212&r1=400211&r2=400212&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/testRelative.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/testRelative.java Fri May  5 16:50:12 2006
@@ -5,11 +5,14 @@
 
 import org.apache.derby.tools.ij;
 import org.apache.derby.tools.JDBCDisplayUtil;
+import org.apache.derbyTesting.functionTests.util.TestUtil;
 
 public class testRelative {
+	
+	static final String NO_CURRENT_ROW_SQL_STATE = 
+		(TestUtil.isNetFramework() ? 
+		 "XJ121" : "24000");
    
-   static final String NO_CURRENT_ROW_SQL_STATE = "24000";
-  
    public static void main(String[] args) {
 	   System.out.println("Test testRelative starting");
 	   Connection con = null;
@@ -59,45 +62,50 @@
 		
 			pStmt.executeBatch();
 			con.commit();
+		} catch(SQLException se) {
+			unexpectedSQLException(se);
+		} catch(Throwable t) {
+			System.out.println("FAIL--unexpected exception: "+t.getMessage());
+			t.printStackTrace(System.out);
+		}
+		try {
+			testScrolling(ResultSet.CONCUR_READ_ONLY, con);
+			testScrolling(ResultSet.CONCUR_UPDATABLE, con);
+		} catch(Throwable e) {
+			System.out.println("FAIL -- unexpected exception: "+e.getMessage());
+			e.printStackTrace(System.out);
+			
+		}
+	}
 
-			stmt1 = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
-		        rs = stmt1.executeQuery("select * from testRelative");						
-
-   			rs.next(); // First Record
-   			returnValue = rs.getString("name");
-   			System.out.println("Value="+returnValue);
-
-   			rs.relative(2);
-   			System.out.println("isFirst=" + rs.isFirst() + " isLast=" + rs.isLast() + " isAfterLast=" + rs.isAfterLast());
-   			returnValue = rs.getString("name");
-   			System.out.println("Value="+returnValue);
-
-   			rs.relative(-2);
-   			returnValue = rs.getString("name");
-   			System.out.println("Value="+returnValue);
-                 } catch(SQLException se) {
-		    unexpectedSQLException(se);
-                 } catch(Throwable t) {
-		    System.out.println("FAIL--unexpected exception: "+t.getMessage());
-		    t.printStackTrace(System.out);
-                 }
-
-                 try {
-
-   			rs.relative(10);
-   			System.out.println("isFirst=" + rs.isFirst() + " isLast=" + rs.isLast() + " isAfterLast=" + rs.isAfterLast());
-
-   			returnValue = rs.getString("name");
-   			System.out.println("Value="+returnValue);
-
- 		} catch(SQLException sqle) {
- 		   expectedException(sqle, NO_CURRENT_ROW_SQL_STATE);
- 		} catch(Throwable e) {
- 		   System.out.println("FAIL -- unexpected exception: "+e.getMessage());
-                   e.printStackTrace(System.out);
-
- 		}
-      }
+	private static void testScrolling(int concurrency, Connection con) 
+		throws SQLException
+	{
+		Statement stmt1 = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, concurrency);
+		ResultSet rs = stmt1.executeQuery("select * from testRelative");
+		
+		rs.next(); // First Record
+		System.out.println("Value = " + rs.getString("name"));
+		
+		rs.relative(2);
+		System.out.println("Value = " + rs.getString("name"));
+		System.out.println("isFirst = " + rs.isFirst() + 
+						   " isLast = " + rs.isLast() + 
+						   " isAfterLast = " + rs.isAfterLast());
+		rs.relative(-2);
+		System.out.println("Value = " + rs.getString("name"));
+		
+		try {
+			rs.relative(10);
+			System.out.println("Value = " + rs.getString("name"));
+			System.out.println("isFirst = " + rs.isFirst() + 
+							   " isLast = " + rs.isLast() + 
+							   " isAfterLast = " + rs.isAfterLast());
+		} catch(SQLException sqle) {
+			
+			expectedException(sqle, NO_CURRENT_ROW_SQL_STATE);
+		} 
+	}
      
       /**
 	   *  Print the expected Exception's details if the SQLException SQLState
@@ -109,16 +117,17 @@
 	   **/
 	static private void expectedException (SQLException se, String expectedSQLState) {
            if( se.getSQLState() != null && (se.getSQLState().equals(expectedSQLState))) { 
-                System.out.println("PASS -- expected exception");
-                while (se != null) {
-                    System.out.println("SQLSTATE("+se.getSQLState()+"): "+se.getMessage());
-                    se = se.getNextException();
-                }
+                System.out.println("PASS -- expected exception");               
             } else {
 	        System.out.println("FAIL--Unexpected SQLException: " +
 							   "SQLSTATE(" +se.getSQLState() + ")" +
 							   se.getMessage());
-	        se.printStackTrace(System.out);
+			while (se != null) {
+				System.out.println("SQLSTATE("+se.getSQLState()+"): "+se.getMessage());
+				se.printStackTrace(System.out);
+				se = se.getNextException();
+			}
+			 
 	    }
 	}