return null;
}
+ /**
+ * Convenience method for finding a specific row in an indexed table which
+ * matches a given row "pattern. See {@link #findRow(Map)} for details on
+ * the rowPattern.
+ *
+ * @param table the table to search
+ * @param index index to assist the search
+ * @param rowPattern pattern to be used to find the row
+ * @return the matching row or {@code null} if a match could not be found.
+ */
+ public static Map<String,Object> findRow(Table table, Index index,
+ Map<String,Object> rowPattern)
+ throws IOException
+ {
+ Cursor cursor = createIndexCursor(table, index);
+ if(cursor.findRow(rowPattern)) {
+ return cursor.getCurrentRow();
+ }
+ return null;
+ }
+
+ /**
+ * Convenience method for finding a specific row in a table which matches a
+ * given row "pattern. See {@link #findRow(Column,Object)} for details on
+ * the pattern.
+ * <p>
+ * Note, a {@code null} result value is ambiguous in that it could imply no
+ * match or a matching row with {@code null} for the desired value. If
+ * distinguishing this situation is important, you will need to use a Cursor
+ * directly instead of this convenience method.
+ *
+ * @param table the table to search
+ * @param index index to assist the search
+ * @param column column whose value should be returned
+ * @param columnPattern column being matched by the valuePattern
+ * @param valuePattern value from the columnPattern which will match the
+ * desired row
+ * @return the matching row or {@code null} if a match could not be found.
+ */
+ public static Object findValue(Table table, Index index, Column column,
+ Column columnPattern, Object valuePattern)
+ throws IOException
+ {
+ Cursor cursor = createIndexCursor(table, index);
+ if(cursor.findRow(columnPattern, valuePattern)) {
+ return cursor.getCurrentRowValue(column);
+ }
+ return null;
+ }
+
public Table getTable() {
return _table;
}
return getTable().getPageChannel();
}
- public Position getCurrentPosition() {
- return _curPos;
+ /**
+ * Returns the current state of the cursor which can be restored at a future
+ * point in time by a call to {@link #restoreSavepoint}.
+ */
+ public Savepoint getSavepoint() {
+ return new Savepoint(_curPos, _prevPos);
}
/**
- * Moves the cursor to a position previously returned from
- * {@link #getCurrentPosition}.
+ * Moves the cursor to a savepoint previously returned from
+ * {@link #getSavepoint}.
*/
- public void setCurrentPosition(Position curPos)
+ public void restoreSavepoint(Savepoint savepoint)
throws IOException
{
- restorePosition(curPos);
+ restorePosition(savepoint.getCurrentPosition(),
+ savepoint.getPreviousPosition());
}
/**
}
+ /**
+ * Value object which represents a complete save state of the cursor.
+ */
+ public static final class Savepoint
+ {
+ private final Position _curPos;
+ private final Position _prevPos;
+
+ private Savepoint(Position curPos, Position prevPos) {
+ _curPos = curPos;
+ _prevPos = prevPos;
+ }
+
+ public Position getCurrentPosition() {
+ return _curPos;
+ }
+
+ private Position getPreviousPosition() {
+ return _prevPos;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + " CurPosition " + _curPos +
+ ", PrevPosition " + _prevPos;
+ }
+ }
+
/**
* Value object which maintains the current position of the cursor.
*/
assertEquals(3, cursor.moveNextRows(3));
assertFalse(cursor.isBeforeFirst());
assertFalse(cursor.isAfterLast());
+
+ Map<String,Object> expectedRow = cursor.getCurrentRow();
+ Cursor.Savepoint savepoint = cursor.getSavepoint();
+ assertEquals(2, cursor.movePreviousRows(2));
+ assertEquals(2, cursor.moveNextRows(2));
+ assertTrue(cursor.moveToNextRow());
+ assertTrue(cursor.moveToPreviousRow());
+ assertEquals(expectedRow, cursor.getCurrentRow());
+
while(cursor.moveToNextRow()) {
foundRows.add(cursor.getCurrentRow());
}
assertTrue(cursor.isAfterLast());
assertEquals(0, cursor.moveNextRows(3));
+
+ cursor.beforeFirst();
+ assertTrue(cursor.isBeforeFirst());
+ assertFalse(cursor.isAfterLast());
+
+ cursor.afterLast();
+ assertFalse(cursor.isBeforeFirst());
+ assertTrue(cursor.isAfterLast());
+
+ cursor.restoreSavepoint(savepoint);
+ assertEquals(expectedRow, cursor.getCurrentRow());
}
public void testSearch() throws Exception {
Table table = db.getTable("test");
Cursor cursor = Cursor.createCursor(table);
- doTestSearch(table, cursor);
+ doTestSearch(table, cursor, null);
db.close();
}
- private void doTestSearch(Table table, Cursor cursor) throws Exception {
- List<Map<String,Object>> expectedRows = createTestTableData();
-
+ private void doTestSearch(Table table, Cursor cursor, Index index)
+ throws Exception
+ {
assertTrue(cursor.findRow(table.getColumn("id"), 3));
assertEquals(createExpectedRow("id", 3,
"value", "data" + 3),
cursor.getCurrentRow());
assertFalse(cursor.findRow(createExpectedRow(
- "id", 13,
- "value", "data" + 8)));
+ "id", 8,
+ "value", "data" + 13)));
+ assertFalse(cursor.findRow(table.getColumn("id"), 13));
assertEquals(createExpectedRow("id", 6,
"value", "data" + 6),
cursor.getCurrentRow());
+
+ assertTrue(cursor.findRow(createExpectedRow(
+ "value", "data" + 7)));
+ assertEquals(createExpectedRow("id", 7,
+ "value", "data" + 7),
+ cursor.getCurrentRow());
+
+ assertTrue(cursor.findRow(table.getColumn("value"), "data" + 2));
+ assertEquals(createExpectedRow("id", 2,
+ "value", "data" + 2),
+ cursor.getCurrentRow());
assertEquals("data" + 9,
Cursor.findValue(table,
table.getColumn("value"),
table.getColumn("id"), 9));
+ assertEquals(createExpectedRow("id", 9,
+ "value", "data" + 9),
+ Cursor.findRow(table,
+ createExpectedRow("id", 9)));
+ if(index != null) {
+ assertEquals("data" + 9,
+ Cursor.findValue(table, index,
+ table.getColumn("value"),
+ table.getColumn("id"), 9));
+ assertEquals(createExpectedRow("id", 9,
+ "value", "data" + 9),
+ Cursor.findRow(table, index,
+ createExpectedRow("id", 9)));
+ }
}
public void testReverse() throws Exception {
Table table = db.getTable("test");
Index idx = table.getIndexes().get(0);
Cursor cursor = Cursor.createIndexCursor(table, idx);
- doTestSearch(table, cursor);
+ doTestSearch(table, cursor, idx);
db.close();
}