]> source.dussan.org Git - jackcess.git/commitdiff
Add Cursor.findRow(RowId) for moving to a specific Table row using only the RowId
authorJames Ahlborn <jtahlborn@yahoo.com>
Wed, 11 Jun 2014 22:23:04 +0000 (22:23 +0000)
committerJames Ahlborn <jtahlborn@yahoo.com>
Wed, 11 Jun 2014 22:23:04 +0000 (22:23 +0000)
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@864 f203690c-595d-4dc9-a70b-905162fa7fd2

src/changes/changes.xml
src/main/java/com/healthmarketscience/jackcess/Cursor.java
src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java
src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java
src/test/java/com/healthmarketscience/jackcess/CursorTest.java

index 644f4c30d2bccfceff110aca93e89b879b8a63d4..59af706453aa27528a9fe05d73beae2cc6f77136 100644 (file)
@@ -4,6 +4,12 @@
     <author email="javajedi@users.sf.net">Tim McCune</author>
   </properties>
   <body>
+    <release version="2.0.5" date="TBD">
+      <action dev="jahlborn" type="add">
+        Add Cursor.findRow(RowId) for moving to a specific Table row using
+        only the RowId.
+      </action>
+    </release>
     <release version="2.0.4" date="2014-04-05">
       <action dev="jahlborn" type="add">
         Add ColumnValidator interface which allows column values to be easily
index b9c47f17e49ce3e8cd89b0bdca7a0a209964e677..956f545a22e2d2180041d8d5166123d4903570a0 100644 (file)
@@ -224,6 +224,15 @@ public interface Cursor extends Iterable<Row>
    *         otherwise
    */
   public boolean moveToPreviousRow() throws IOException;
+  
+  /**
+   * Moves to the row with the given rowId.  If the row is not found (or an
+   * exception is thrown), the cursor is restored to its previous state.
+   * 
+   * @return {@code true} if a valid row was found with the given id,
+   *         {@code false} if no row was found
+   */
+  public boolean findRow(RowId rowId) throws IOException;
 
   /**
    * Moves to the first row (as defined by the cursor) where the given column
index 06cda47cf6cfa1c26a90a6bcf0749c340b4405f1..1521e3b4c781ce7bd9f1ef59e86bd8e18e851afa 100644 (file)
@@ -38,6 +38,7 @@ import com.healthmarketscience.jackcess.Column;
 import com.healthmarketscience.jackcess.Cursor;
 import com.healthmarketscience.jackcess.CursorBuilder;
 import com.healthmarketscience.jackcess.Row;
+import com.healthmarketscience.jackcess.RowId;
 import com.healthmarketscience.jackcess.RuntimeIOException;
 import com.healthmarketscience.jackcess.impl.TableImpl.RowState;
 import com.healthmarketscience.jackcess.util.ColumnMatcher;
@@ -417,6 +418,34 @@ public abstract class CursorImpl implements Cursor
     return(!_curPos.equals(getDirHandler(moveForward).getEndPosition()));
   }
 
+  public boolean findRow(RowId rowId) throws IOException
+  {
+    RowIdImpl rowIdImpl = (RowIdImpl)rowId;
+    PositionImpl curPos = _curPos;
+    PositionImpl prevPos = _prevPos;
+    boolean found = false;
+    try {
+      reset(MOVE_FORWARD);
+      if(TableImpl.positionAtRowHeader(_rowState, rowIdImpl) == null) {
+        return false;
+      }
+      restorePosition(getRowPosition(rowIdImpl));
+      if(!isCurrentRowValid()) {
+        return false;
+      }
+      found = true;
+      return true;
+    } finally {
+      if(!found) {
+        try {
+          restorePosition(curPos, prevPos);
+        } catch(IOException e) {
+          LOG.error("Failed restoring position", e);
+        }
+      }
+    }
+  }
+
   public boolean findFirstRow(Column columnPattern, Object valuePattern)
     throws IOException
   {
@@ -688,6 +717,13 @@ public abstract class CursorImpl implements Cursor
     return getClass().getSimpleName() + " CurPosition " + _curPos +
       ", PrevPosition " + _prevPos;
   }
+
+  /**
+   * Returns the appropriate position information for the given row (which is
+   * the current row and is valid).
+   */
+  protected abstract PositionImpl getRowPosition(RowIdImpl rowId) 
+    throws IOException;
     
   /**
    * Finds the next non-deleted row after the given row (as defined by this
index c2f0280b195a4386e396bef1a1e2ae3d2388448e..68870d9b3483c45de837bb9c6788308804b448a3 100644 (file)
@@ -121,6 +121,18 @@ public class IndexCursorImpl extends CursorImpl implements IndexCursor
     return cursor;
   }  
 
+  private Set<String> getIndexEntryPattern()
+  {
+    if(_indexEntryPattern == null) {
+      // init our set of index column names
+      _indexEntryPattern = new HashSet<String>();
+      for(IndexData.ColumnDescriptor col : getIndex().getColumns()) {
+        _indexEntryPattern.add(col.getName());
+      }
+    }
+    return _indexEntryPattern;
+  }
+
   public IndexImpl getIndex() {
     return _index;
   }
@@ -222,6 +234,15 @@ public class IndexCursorImpl extends CursorImpl implements IndexCursor
     super.restorePositionImpl(curPos, prevPos);
   }
 
+  @Override
+  protected PositionImpl getRowPosition(RowIdImpl rowId) throws IOException
+  {
+    // we need to get the index entry which corresponds with this row
+    Row row = getTable().getRow(getRowState(), rowId, getIndexEntryPattern());
+    _entryCursor.beforeEntry(getTable().asRow(row));
+    return new IndexPosition(_entryCursor.getNextEntry());
+  }
+
   @Override
   protected boolean findAnotherRowImpl(
       ColumnImpl columnPattern, Object valuePattern, boolean moveForward,
@@ -348,16 +369,8 @@ public class IndexCursorImpl extends CursorImpl implements IndexCursor
                                              ColumnMatcher columnMatcher)
     throws IOException
   {
-    if(_indexEntryPattern == null) {
-      // init our set of index column names
-      _indexEntryPattern = new HashSet<String>();
-      for(IndexData.ColumnDescriptor col : getIndex().getColumns()) {
-        _indexEntryPattern.add(col.getName());
-      }
-    }
-
     // check the next row to see if it actually matches
-    Row row = getCurrentRow(_indexEntryPattern);
+    Row row = getCurrentRow(getIndexEntryPattern());
 
     for(IndexData.ColumnDescriptor col : getIndex().getColumns()) {
       String columnName = col.getName();
index 9fe8dc40e07b03c4dd2bd306f63a81a5858d60fb..0f5e37ffa6af581f31858d5fa37e7aee6d0bff06 100644 (file)
@@ -84,6 +84,12 @@ public class TableScanCursor extends CursorImpl
     super.restorePositionImpl(curPos, prevPos);
   }
 
+  @Override
+  protected PositionImpl getRowPosition(RowIdImpl rowId) throws IOException
+  {
+    return new ScanPosition(rowId);
+  }
+
   @Override
   protected PositionImpl findAnotherPosition(
       RowState rowState, PositionImpl curPos, boolean moveForward)
index bafee578d2a7bc7246e18dc6abd3def2a8df611e..cf55e2b6dbc3cb55d542fc08437cc8f1de73cf99 100644 (file)
@@ -1205,5 +1205,75 @@ public class CursorTest extends TestCase {
     }    
   }
   
+  public void testFindByRowId() throws Exception {
+    for (final FileFormat fileFormat : JetFormatTest.SUPPORTED_FILEFORMATS) {
+      Database db = createTestTable(fileFormat);
+
+      Table table = db.getTable("test");
+      Cursor cursor = CursorBuilder.createCursor(table);
+      doTestFindByRowId(cursor);
+      db.close();
+    }
+  }
+
+  public void testFindByRowIdIndex() throws Exception {
+    for (final TestDB indexCursorDB : INDEX_CURSOR_DBS) {
+      Database db = createTestIndexTable(indexCursorDB);
+
+      Table table = db.getTable("test");
+      Index idx = table.getIndexes().get(0);
+
+      assertTable(createUnorderedTestTableData(), table);
+
+      Cursor cursor = CursorBuilder.createCursor(idx);
+      doTestFindByRowId(cursor);
+
+      db.close();
+    }
+  }
+
+  private static void doTestFindByRowId(Cursor cursor) 
+    throws Exception
+  {
+    for(int i = 0; i < 3; ++i) {
+      cursor.moveToNextRow();
+    } 
+
+    Row r1 = cursor.getCurrentRow();
+
+    for(int i = 0; i < 3; ++i) {
+      cursor.moveToNextRow();
+    } 
+
+    Row r2 = cursor.getCurrentRow();
+
+    doTestFindByRowId(cursor, r1, 2);
+
+    doTestFindByRowId(cursor, r2, 5);
+  } 
+
+  private static void doTestFindByRowId(Cursor cursor, Row row, int id)
+    throws Exception
+  {
+    cursor.reset();
+    assertTrue(cursor.findRow(row.getId()));
+    Row rFound = cursor.getCurrentRow();
+    assertEquals(id, rFound.get("id"));
+    assertEquals(row, rFound);
+    Cursor.Savepoint save = cursor.getSavepoint();
+
+    assertTrue(cursor.moveToNextRow());
+    assertEquals(id + 1, cursor.getCurrentRow().get("id"));
+
+    cursor.restoreSavepoint(save);
+
+    assertTrue(cursor.moveToPreviousRow());
+    assertEquals(id - 1, cursor.getCurrentRow().get("id"));
+
+    assertFalse(cursor.findRow(RowIdImpl.FIRST_ROW_ID));
+
+    assertEquals(id - 1, cursor.getCurrentRow().get("id"));    
+  }
+
 }