You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2013/05/30 01:07:11 UTC

svn commit: r1487668 - in /jena/Experimental/jena-jdbc/jena-jdbc-core/src: main/java/org/apache/jena/jdbc/results/ test/java/org/apache/jena/jdbc/results/

Author: rvesse
Date: Wed May 29 23:07:11 2013
New Revision: 1487668

URL: http://svn.apache.org/r1487668
Log:
Expand test coverage for scrollable result sets, fix various implementation bugs

Modified:
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedResults.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedSelectResults.java
    jena/Experimental/jena-jdbc/jena-jdbc-core/src/test/java/org/apache/jena/jdbc/results/AbstractResultSetTests.java

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedResults.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedResults.java?rev=1487668&r1=1487667&r2=1487668&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedResults.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedResults.java Wed May 29 23:07:11 2013
@@ -26,8 +26,8 @@ import org.apache.jena.jdbc.statements.J
 import com.hp.hpl.jena.query.QueryExecution;
 
 /**
- * Represents a set of streamed results backed by some {@link QueryExecution},
- * streamed results are considered to be forward only
+ * Represents a set of materialized results backed by some {@link QueryExecution},
+ * materialized results permit scrolling but are not sensitive to changes in the underlying data
  * 
  * @param <T>
  *            Type of the underlying result rows
@@ -125,13 +125,13 @@ public abstract class MaterializedResult
             // Try and move to before first row
             this.beforeFirst();
             return false;
-        } else if (row >= this.getTotalRows()) {
+        } else if (row > this.getTotalRows()) {
             // Try and move to after last row
             this.afterLast();
             return false;
         } else if (row <= 0) {
             // Move to a row relative to the end of the result set
-            int destRow = this.getTotalRows() + row;
+            int destRow = this.getTotalRows() + 1 + row;
             if (destRow < 1) {
                 // Move to before first
                 this.beforeFirst();
@@ -182,6 +182,10 @@ public abstract class MaterializedResult
     public final void beforeFirst() throws SQLException {
         if (this.isClosed())
             throw new SQLException("Result Set is closed");
+        
+        // Are we after the last row?  If so reset current row or movePrevious() may break
+        if (this.isAfterLast()) 
+            this.currRow = this.getTotalRows();
 
         // Move to start of results if necessary
         while (this.hasPrevious()) {
@@ -212,13 +216,29 @@ public abstract class MaterializedResult
         // Are we already at the first row?
         if (this.currRow == 1)
             return true;
-
-        // Otherwise move backwards to it
-        while (this.hasPrevious()) {
-            this.currItem = this.movePrevious();
-            this.currRow--;
+        
+        // Are we after the last row?  If so reset current row or movePrevious() may break
+        if (this.isAfterLast()) 
+            this.currRow = this.getTotalRows();
+
+        // Before first row?
+        if (this.isBeforeFirst()) {
+            // Need to move forwards to first row
+            if (this.hasNext()) {
+                this.currItem = this.moveNext();
+                this.currRow = 1;
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            // Otherwise move backwards to it
+            while (this.hasPrevious()) {
+                this.currItem = this.movePrevious();
+                this.currRow--;
+            }
+            return true;
         }
-        return true;
     }
 
     @Override
@@ -274,22 +294,36 @@ public abstract class MaterializedResult
     @Override
     public final boolean last() throws SQLException {
         if (this.isClosed())
-            throw new SQLException("Jena JDBC Result Sets are forward-only");
+            throw new SQLException("Result Set is closed");
 
         // If no rows this should always return false
         if (this.getTotalRows() == 0)
             return false;
-
+        
         // Are we already at the last row?
         if (this.currRow == this.getTotalRows())
             return true;
 
-        // Otherwise move forwards to the last row
-        while (this.hasNext()) {
-            this.currItem = this.moveNext();
-            this.currRow++;
+        // Are we after the last row?
+        if (this.isAfterLast()) {
+            this.currRow = this.getTotalRows();
+            
+            // Move backwards to last row
+            if (this.hasPrevious()) {
+                this.currItem = this.movePrevious();
+                this.currRow = this.getTotalRows();
+                return true;
+            } else {
+                return false;
+            }
+        } else {
+            // Otherwise move forwards to the last row
+            while (this.hasNext()) {
+                this.currItem = this.moveNext();
+                this.currRow++;
+            }
+            return true;
         }
-        return true;
 
     }
 
@@ -309,7 +343,7 @@ public abstract class MaterializedResult
             }
         }
     }
-    
+
     @Override
     public final boolean previous() throws SQLException {
         if (this.isClosed()) {

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedSelectResults.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedSelectResults.java?rev=1487668&r1=1487667&r2=1487668&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedSelectResults.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/main/java/org/apache/jena/jdbc/results/MaterializedSelectResults.java Wed May 29 23:07:11 2013
@@ -42,6 +42,7 @@ public class MaterializedSelectResults e
 
     private ResultSetRewindable innerResults;
     private Stack<Binding> previousResults = new Stack<Binding>();
+    private Stack<Binding> nextResults = new Stack<Binding>();
     private List<String> columns;
     private SelectResultsMetadata metadata;
 
@@ -126,7 +127,7 @@ public class MaterializedSelectResults e
     protected boolean hasNext() throws SQLException {
         // No null check here because superclass will not call us after we are
         // closed and set to null
-        return this.innerResults.hasNext();
+        return !this.nextResults.isEmpty() || this.innerResults.hasNext();
     }
 
     /**
@@ -136,7 +137,14 @@ public class MaterializedSelectResults e
     protected Binding moveNext() throws SQLException {
         // No null check here because superclass will not call us after we are
         // closed and set to null
-        this.previousResults.push(this.innerResults.nextBinding());
+
+        if (this.nextResults.isEmpty()) {
+            // Need to go to underlying result set
+            this.previousResults.push(this.innerResults.nextBinding());
+        } else {
+            // Continue through results we've previously seen and moved backwards from
+            this.previousResults.push(this.nextResults.pop());
+        }
         return this.previousResults.peek();
     }
 
@@ -147,9 +155,10 @@ public class MaterializedSelectResults e
 
     @Override
     protected Binding movePrevious() throws SQLException {
-        return this.previousResults.pop();
+        this.nextResults.push(this.previousResults.pop());
+        return this.nextResults.peek();
     }
-    
+
     @Override
     protected int getTotalRows() {
         return this.innerResults.size();

Modified: jena/Experimental/jena-jdbc/jena-jdbc-core/src/test/java/org/apache/jena/jdbc/results/AbstractResultSetTests.java
URL: http://svn.apache.org/viewvc/jena/Experimental/jena-jdbc/jena-jdbc-core/src/test/java/org/apache/jena/jdbc/results/AbstractResultSetTests.java?rev=1487668&r1=1487667&r2=1487668&view=diff
==============================================================================
--- jena/Experimental/jena-jdbc/jena-jdbc-core/src/test/java/org/apache/jena/jdbc/results/AbstractResultSetTests.java (original)
+++ jena/Experimental/jena-jdbc/jena-jdbc-core/src/test/java/org/apache/jena/jdbc/results/AbstractResultSetTests.java Wed May 29 23:07:11 2013
@@ -982,4 +982,323 @@ public abstract class AbstractResultSetT
         rset.close();
         Assert.assertTrue(rset.isClosed());
     }
+    
+    /**
+     * Tests movement through SELECT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_select_movement_07() throws SQLException {
+        ResultSet rset = this.createResults(ds, "SELECT * { ?s ?p ?o . } LIMIT 5", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Can move to various absolute rows
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.absolute(3));
+        Assert.assertTrue(rset.absolute(2));
+        Assert.assertTrue(rset.absolute(4));
+        Assert.assertTrue(rset.absolute(5));
+        Assert.assertTrue(rset.absolute(-1));
+        Assert.assertTrue(rset.absolute(-2));
+        Assert.assertTrue(rset.absolute(-3));
+        Assert.assertTrue(rset.absolute(-4));
+        Assert.assertTrue(rset.absolute(-5));
+        
+        // 0 is treated as moving to before first
+        Assert.assertFalse(rset.absolute(0));
+        Assert.assertTrue(rset.isBeforeFirst());
+        
+        // 1 is treated as moving to first row
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.isFirst());
+        
+        // -1 is treated as moving to last row
+        Assert.assertTrue(rset.absolute(-1));
+        Assert.assertTrue(rset.isLast());
+        
+        // Moving to a row beyond end positions us after last and returns false
+        Assert.assertFalse(rset.absolute(6));
+        Assert.assertTrue(rset.isAfterLast());
+        
+        // Moving to a row before start positions us before first and returns false
+        Assert.assertFalse(rset.absolute(-6));
+        Assert.assertTrue(rset.isBeforeFirst());
+        
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through SELECT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_select_movement_08() throws SQLException {
+        ResultSet rset = this.createResults(ds, "SELECT * { ?s ?p ?o . } LIMIT 2", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Can move forwards to after last row
+        rset.afterLast();
+        Assert.assertTrue(rset.isAfterLast());
+        
+        // Can move backwards to last row
+        Assert.assertTrue(rset.last());
+        Assert.assertTrue(rset.isLast());
+
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_01() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 1", ResultSet.TYPE_FORWARD_ONLY);
+        Assert.assertEquals(ResultSet.TYPE_FORWARD_ONLY, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+
+        // Expect exactly one row we can move to
+        Assert.assertTrue(rset.next());
+        Assert.assertFalse(rset.isAfterLast());
+        Assert.assertTrue(rset.isLast());
+        Assert.assertFalse(rset.next());
+
+        Assert.assertTrue(rset.isAfterLast());
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_02() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 1", ResultSet.TYPE_FORWARD_ONLY);
+        Assert.assertEquals(ResultSet.TYPE_FORWARD_ONLY, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Expect exactly one row we can move to
+        Assert.assertTrue(rset.next());
+        Assert.assertFalse(rset.isAfterLast());
+        Assert.assertTrue(rset.isLast());
+        Assert.assertFalse(rset.next());
+
+        // Attempting to move backwards in a forwards only result set should result in an error
+        try {
+            rset.beforeFirst();
+            Assert.fail("Should not be permitted to move backwards in a FORWARD_ONLY result set");
+        } catch (SQLException e) {
+            // Expected
+        } finally {
+
+            Assert.assertTrue(rset.isAfterLast());
+            rset.close();
+            Assert.assertTrue(rset.isClosed());
+        }
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_03() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 1", ResultSet.TYPE_FORWARD_ONLY);
+        Assert.assertEquals(ResultSet.TYPE_FORWARD_ONLY, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+
+        // Can move forwards to last row
+        Assert.assertTrue(rset.last());
+        Assert.assertFalse(rset.isAfterLast());
+        Assert.assertTrue(rset.isLast());
+        Assert.assertFalse(rset.next());
+
+        Assert.assertTrue(rset.isAfterLast());
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_04() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 1", ResultSet.TYPE_FORWARD_ONLY);
+        Assert.assertEquals(ResultSet.TYPE_FORWARD_ONLY, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+
+        // Can move forwards to after last row
+        rset.afterLast();
+        Assert.assertTrue(rset.isAfterLast());
+
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_05() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 1", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Expect exactly one row we can move to
+        Assert.assertTrue(rset.next());
+        Assert.assertFalse(rset.isAfterLast());
+        Assert.assertTrue(rset.isLast());
+        Assert.assertFalse(rset.next());
+
+        // Attempting to move backwards in a scrollable result set should result set should be fine
+        rset.beforeFirst();
+        Assert.assertTrue(rset.isBeforeFirst());
+
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_06() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 2", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Can move forwards to first row
+        Assert.assertTrue(rset.next());
+        Assert.assertTrue(rset.isFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Then can move forwards to second row
+        Assert.assertTrue(rset.next());
+        Assert.assertTrue(rset.isLast());
+
+        // Can move backwards to previous row
+        Assert.assertTrue(rset.previous());
+        Assert.assertTrue(rset.isFirst());
+
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_07() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 5", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Can move to various absolute rows
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.absolute(3));
+        Assert.assertTrue(rset.absolute(2));
+        Assert.assertTrue(rset.absolute(4));
+        Assert.assertTrue(rset.absolute(5));
+        Assert.assertTrue(rset.absolute(-1));
+        Assert.assertTrue(rset.absolute(-2));
+        Assert.assertTrue(rset.absolute(-3));
+        Assert.assertTrue(rset.absolute(-4));
+        Assert.assertTrue(rset.absolute(-5));
+        
+        // 0 is treated as moving to before first
+        Assert.assertFalse(rset.absolute(0));
+        Assert.assertTrue(rset.isBeforeFirst());
+        
+        // 1 is treated as moving to first row
+        Assert.assertTrue(rset.absolute(1));
+        Assert.assertTrue(rset.isFirst());
+        
+        // -1 is treated as moving to last row
+        Assert.assertTrue(rset.absolute(-1));
+        Assert.assertTrue(rset.isLast());
+        
+        // Moving to a row beyond end positions us after last and returns false
+        Assert.assertFalse(rset.absolute(6));
+        Assert.assertTrue(rset.isAfterLast());
+        
+        // Moving to a row before start positions us before first and returns false
+        Assert.assertFalse(rset.absolute(-6));
+        Assert.assertTrue(rset.isBeforeFirst());
+        
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
+    
+    /**
+     * Tests movement through CONSTRUCT results
+     * 
+     * @throws SQLException
+     */
+    @Test
+    public void test_results_construct_movement_08() throws SQLException {
+        ResultSet rset = this.createResults(ds, "CONSTRUCT WHERE { ?s ?p ?o . } LIMIT 2", ResultSet.TYPE_SCROLL_INSENSITIVE);
+        Assert.assertEquals(ResultSet.TYPE_SCROLL_INSENSITIVE, rset.getType());
+        Assert.assertNotNull(rset);
+        Assert.assertFalse(rset.isClosed());
+        Assert.assertTrue(rset.isBeforeFirst());
+        Assert.assertFalse(rset.isLast());
+        
+        // Can move forwards to after last row
+        rset.afterLast();
+        Assert.assertTrue(rset.isAfterLast());
+        
+        // Can move backwards to last row
+        Assert.assertTrue(rset.last());
+        Assert.assertTrue(rset.isLast());
+
+        rset.close();
+        Assert.assertTrue(rset.isClosed());
+    }
 }