storage: fixes behaviour of cursor delete_current on start item (#7646)

Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
This commit is contained in:
Mateusz Morusiewicz
2024-04-17 08:39:21 +02:00
committed by GitHub
parent 24225d0a88
commit 70db3d8276
2 changed files with 44 additions and 0 deletions

View File

@ -181,6 +181,7 @@ impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> Walker<'cursor, T, CURSOR> {
impl<'cursor, T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> Walker<'cursor, T, CURSOR> {
/// Delete current item that walker points to.
pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
self.start.take();
self.cursor.delete_current()
}
}
@ -223,6 +224,7 @@ impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> ReverseWalker<'cursor, T, CURSOR>
impl<'cursor, T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> ReverseWalker<'cursor, T, CURSOR> {
/// Delete current item that walker points to.
pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
self.start.take();
self.cursor.delete_current()
}
}
@ -321,6 +323,7 @@ impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> RangeWalker<'cursor, T, CURSOR> {
impl<'cursor, T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> RangeWalker<'cursor, T, CURSOR> {
/// Delete current item that walker points to.
pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
self.start.take();
self.cursor.delete_current()
}
}
@ -353,6 +356,7 @@ where
impl<'cursor, T: DupSort, CURSOR: DbCursorRW<T> + DbDupCursorRO<T>> DupWalker<'cursor, T, CURSOR> {
/// Delete current item that walker points to.
pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
self.start.take();
self.cursor.delete_current()
}
}

View File

@ -482,6 +482,7 @@ mod tests {
const ERROR_APPEND: &str = "Not able to append the value to the table.";
const ERROR_UPSERT: &str = "Not able to upsert the value to the table.";
const ERROR_GET: &str = "Not able to get value from table.";
const ERROR_DEL: &str = "Not able to delete from table.";
const ERROR_COMMIT: &str = "Not able to commit transaction.";
const ERROR_RETURN_VALUE: &str = "Mismatching result.";
const ERROR_INIT_TX: &str = "Failed to create a MDBX transaction.";
@ -511,6 +512,45 @@ mod tests {
tx.commit().expect(ERROR_COMMIT);
}
#[test]
fn db_dup_cursor_delete_first() {
let db: Arc<DatabaseEnv> = create_test_db(DatabaseEnvKind::RW);
let tx = db.tx_mut().expect(ERROR_INIT_TX);
let mut dup_cursor = tx.cursor_dup_write::<PlainStorageState>().unwrap();
let entry_0 = StorageEntry { key: B256::with_last_byte(1), value: U256::from(0) };
let entry_1 = StorageEntry { key: B256::with_last_byte(1), value: U256::from(1) };
dup_cursor.upsert(Address::with_last_byte(1), entry_0).expect(ERROR_UPSERT);
dup_cursor.upsert(Address::with_last_byte(1), entry_1).expect(ERROR_UPSERT);
assert_eq!(
dup_cursor.walk(None).unwrap().collect::<Result<Vec<_>, _>>(),
Ok(vec![(Address::with_last_byte(1), entry_0), (Address::with_last_byte(1), entry_1),])
);
let mut walker = dup_cursor.walk(None).unwrap();
walker.delete_current().expect(ERROR_DEL);
assert_eq!(walker.next(), Some(Ok((Address::with_last_byte(1), entry_1))));
// Check the tx view - it correctly holds entry_1
assert_eq!(
tx.cursor_dup_read::<PlainStorageState>()
.unwrap()
.walk(None)
.unwrap()
.collect::<Result<Vec<_>, _>>(),
Ok(vec![
(Address::with_last_byte(1), entry_1), // This is ok - we removed entry_0
])
);
// Check the remainder of walker
assert_eq!(walker.next(), None);
}
#[test]
fn db_cursor_walk() {
let env = create_test_db(DatabaseEnvKind::RW);