aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/changes/changes.xml6
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/Cursor.java9
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java36
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java31
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java6
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/CursorTest.java70
6 files changed, 149 insertions, 9 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 644f4c3..59af706 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -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
diff --git a/src/main/java/com/healthmarketscience/jackcess/Cursor.java b/src/main/java/com/healthmarketscience/jackcess/Cursor.java
index b9c47f1..956f545 100644
--- a/src/main/java/com/healthmarketscience/jackcess/Cursor.java
+++ b/src/main/java/com/healthmarketscience/jackcess/Cursor.java
@@ -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
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java
index 06cda47..1521e3b 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/CursorImpl.java
@@ -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
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java b/src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java
index c2f0280..68870d9 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/IndexCursorImpl.java
@@ -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;
}
@@ -223,6 +235,15 @@ public class IndexCursorImpl extends CursorImpl implements IndexCursor
}
@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,
ColumnMatcher columnMatcher)
@@ -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();
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java b/src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java
index 9fe8dc4..0f5e37f 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/TableScanCursor.java
@@ -85,6 +85,12 @@ public class TableScanCursor extends CursorImpl
}
@Override
+ protected PositionImpl getRowPosition(RowIdImpl rowId) throws IOException
+ {
+ return new ScanPosition(rowId);
+ }
+
+ @Override
protected PositionImpl findAnotherPosition(
RowState rowState, PositionImpl curPos, boolean moveForward)
throws IOException
diff --git a/src/test/java/com/healthmarketscience/jackcess/CursorTest.java b/src/test/java/com/healthmarketscience/jackcess/CursorTest.java
index bafee57..cf55e2b 100644
--- a/src/test/java/com/healthmarketscience/jackcess/CursorTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/CursorTest.java
@@ -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"));
+ }
+
}