mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-25 08:21:10 +00:00
Add methods to PrefixIterator to support iterating from a specific key (#9313)
* Add methods to PrefixIterator to support iterating from a specific key * Expose the decode functions used in iterators for storage maps * Use associated decode function in tests * Revert "Expose the decode functions used in iterators for storage maps" This reverts commit 34f57d92db89646d0c98ea1880df58d58e523b09. * Fix documentation for next_key * Add API for iterating from a specified key for all storage map types * Enhance pagination test * Add API methods to storage map types * Rename next_key to last_key * Rename last_key to last_raw_key * Specify that iteration starts after starting_raw_key * Update documentation on iteration ordering * Rename next_key to previous_key * Enhance pagination unit test * Create unit tests for all kinds of iter_from methods * Define iter_from in terms of iter rather than vice versa * Cargo fmt
This commit is contained in:
@@ -369,6 +369,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_prefix_from(
|
||||
k1: impl EncodeLike<K1>,
|
||||
starting_raw_key: Vec<u8>,
|
||||
) -> Self::PrefixIterator {
|
||||
let mut iter = Self::iter_prefix(k1);
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn iter_key_prefix(k1: impl EncodeLike<K1>) -> Self::PartialKeyIterator {
|
||||
let prefix = G::storage_double_map_final_key1(k1);
|
||||
Self::PartialKeyIterator {
|
||||
@@ -382,6 +391,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_key_prefix_from(
|
||||
k1: impl EncodeLike<K1>,
|
||||
starting_raw_key: Vec<u8>,
|
||||
) -> Self::PartialKeyIterator {
|
||||
let mut iter = Self::iter_key_prefix(k1);
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn drain_prefix(k1: impl EncodeLike<K1>) -> Self::PrefixIterator {
|
||||
let mut iterator = Self::iter_prefix(k1);
|
||||
iterator.drain = true;
|
||||
@@ -404,6 +422,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
|
||||
let mut iter = Self::iter();
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn iter_keys() -> Self::FullKeyIterator {
|
||||
let prefix = G::prefix_hash();
|
||||
Self::FullKeyIterator {
|
||||
@@ -420,6 +444,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::FullKeyIterator {
|
||||
let mut iter = Self::iter_keys();
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn drain() -> Self::Iterator {
|
||||
let mut iterator = Self::iter();
|
||||
iterator.drain = true;
|
||||
@@ -509,6 +539,42 @@ mod test_iterators {
|
||||
prefix
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::hash::Identity;
|
||||
crate::generate_storage_alias!(
|
||||
MyModule,
|
||||
MyDoubleMap => DoubleMap<(u64, Identity), (u64, Identity), u64>
|
||||
);
|
||||
|
||||
MyDoubleMap::insert(1, 10, 100);
|
||||
MyDoubleMap::insert(1, 21, 201);
|
||||
MyDoubleMap::insert(1, 31, 301);
|
||||
MyDoubleMap::insert(1, 41, 401);
|
||||
MyDoubleMap::insert(2, 20, 200);
|
||||
MyDoubleMap::insert(3, 30, 300);
|
||||
MyDoubleMap::insert(4, 40, 400);
|
||||
MyDoubleMap::insert(5, 50, 500);
|
||||
|
||||
let starting_raw_key = MyDoubleMap::storage_double_map_final_key(1, 21);
|
||||
let iter = MyDoubleMap::iter_key_prefix_from(1, starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![31, 41]);
|
||||
|
||||
let starting_raw_key = MyDoubleMap::storage_double_map_final_key(1, 31);
|
||||
let iter = MyDoubleMap::iter_prefix_from(1, starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(41, 401)]);
|
||||
|
||||
let starting_raw_key = MyDoubleMap::storage_double_map_final_key(2, 20);
|
||||
let iter = MyDoubleMap::iter_keys_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(3, 30), (4, 40), (5, 50)]);
|
||||
|
||||
let starting_raw_key = MyDoubleMap::storage_double_map_final_key(3, 30);
|
||||
let iter = MyDoubleMap::iter_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(4, 40, 400), (5, 50, 500)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn double_map_reversible_reversible_iteration() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
|
||||
@@ -153,6 +153,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate all elements in the map after a given key.
|
||||
fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
|
||||
let mut iter = Self::iter();
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
/// Enumerate all keys in the map.
|
||||
fn iter_keys() -> Self::KeyIterator {
|
||||
let prefix = G::prefix_hash();
|
||||
@@ -167,6 +174,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumerate all keys in the map after a given key.
|
||||
fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::KeyIterator {
|
||||
let mut iter = Self::iter_keys();
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
/// Enumerate all elements in the map.
|
||||
fn drain() -> Self::Iterator {
|
||||
let mut iterator = Self::iter();
|
||||
@@ -382,6 +396,28 @@ mod test_iterators {
|
||||
prefix
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::hash::Identity;
|
||||
crate::generate_storage_alias!(MyModule, MyMap => Map<(u64, Identity), u64>);
|
||||
|
||||
MyMap::insert(1, 10);
|
||||
MyMap::insert(2, 20);
|
||||
MyMap::insert(3, 30);
|
||||
MyMap::insert(4, 40);
|
||||
MyMap::insert(5, 50);
|
||||
|
||||
let starting_raw_key = MyMap::storage_map_final_key(3);
|
||||
let iter = MyMap::iter_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(4, 40), (5, 50)]);
|
||||
|
||||
let starting_raw_key = MyMap::storage_map_final_key(2);
|
||||
let iter = MyMap::iter_keys_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![3, 4, 5]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn map_reversible_reversible_iteration() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
//! This is internal api and is subject to change.
|
||||
|
||||
mod double_map;
|
||||
mod map;
|
||||
pub(crate) mod map;
|
||||
mod nmap;
|
||||
mod value;
|
||||
|
||||
|
||||
@@ -329,6 +329,18 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_prefix_from<KP>(
|
||||
kp: KP,
|
||||
starting_raw_key: Vec<u8>,
|
||||
) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>,
|
||||
{
|
||||
let mut iter = Self::iter_prefix(kp);
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn iter_key_prefix<KP>(kp: KP) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>,
|
||||
@@ -342,6 +354,18 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_key_prefix_from<KP>(
|
||||
kp: KP,
|
||||
starting_raw_key: Vec<u8>,
|
||||
) -> KeyPrefixIterator<<K as HasKeyPrefix<KP>>::Suffix>
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>,
|
||||
{
|
||||
let mut iter = Self::iter_key_prefix(kp);
|
||||
iter.set_last_raw_key(starting_raw_key);
|
||||
iter
|
||||
}
|
||||
|
||||
fn drain_prefix<KP>(kp: KP) -> PrefixIterator<(<K as HasKeyPrefix<KP>>::Suffix, V)>
|
||||
where
|
||||
K: HasReversibleKeyPrefix<KP>,
|
||||
@@ -352,10 +376,14 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
}
|
||||
|
||||
fn iter() -> Self::Iterator {
|
||||
Self::iter_from(G::prefix_hash())
|
||||
}
|
||||
|
||||
fn iter_from(starting_raw_key: Vec<u8>) -> Self::Iterator {
|
||||
let prefix = G::prefix_hash();
|
||||
Self::Iterator {
|
||||
prefix: prefix.clone(),
|
||||
previous_key: prefix,
|
||||
prefix,
|
||||
previous_key: starting_raw_key,
|
||||
drain: false,
|
||||
closure: |raw_key_without_prefix, mut raw_value| {
|
||||
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
|
||||
@@ -365,10 +393,14 @@ impl<K: ReversibleKeyGenerator, V: FullCodec, G: StorageNMap<K, V>>
|
||||
}
|
||||
|
||||
fn iter_keys() -> Self::KeyIterator {
|
||||
Self::iter_keys_from(G::prefix_hash())
|
||||
}
|
||||
|
||||
fn iter_keys_from(starting_raw_key: Vec<u8>) -> Self::KeyIterator {
|
||||
let prefix = G::prefix_hash();
|
||||
Self::KeyIterator {
|
||||
prefix: prefix.clone(),
|
||||
previous_key: prefix,
|
||||
prefix,
|
||||
previous_key: starting_raw_key,
|
||||
drain: false,
|
||||
closure: |raw_key_without_prefix| {
|
||||
let (final_key, _) = K::decode_final_key(raw_key_without_prefix)?;
|
||||
@@ -457,6 +489,46 @@ mod test_iterators {
|
||||
prefix
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn n_map_iter_from() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
use crate::{hash::Identity, storage::Key as NMapKey};
|
||||
crate::generate_storage_alias!(
|
||||
MyModule,
|
||||
MyNMap => NMap<Key<(u64, Identity), (u64, Identity), (u64, Identity)>, u64>
|
||||
);
|
||||
|
||||
MyNMap::insert((1, 1, 1), 11);
|
||||
MyNMap::insert((1, 1, 2), 21);
|
||||
MyNMap::insert((1, 1, 3), 31);
|
||||
MyNMap::insert((1, 2, 1), 12);
|
||||
MyNMap::insert((1, 2, 2), 22);
|
||||
MyNMap::insert((1, 2, 3), 32);
|
||||
MyNMap::insert((1, 3, 1), 13);
|
||||
MyNMap::insert((1, 3, 2), 23);
|
||||
MyNMap::insert((1, 3, 3), 33);
|
||||
MyNMap::insert((2, 0, 0), 200);
|
||||
|
||||
type Key = (NMapKey<Identity, u64>, NMapKey<Identity, u64>, NMapKey<Identity, u64>);
|
||||
|
||||
let starting_raw_key = MyNMap::storage_n_map_final_key::<Key, _>((1, 2, 2));
|
||||
let iter = MyNMap::iter_key_prefix_from((1,), starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(2, 3), (3, 1), (3, 2), (3, 3)]);
|
||||
|
||||
let starting_raw_key = MyNMap::storage_n_map_final_key::<Key, _>((1, 3, 1));
|
||||
let iter = MyNMap::iter_prefix_from((1, 3), starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(2, 23), (3, 33)]);
|
||||
|
||||
let starting_raw_key = MyNMap::storage_n_map_final_key::<Key, _>((1, 3, 2));
|
||||
let iter = MyNMap::iter_keys_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![(1, 3, 3), (2, 0, 0)]);
|
||||
|
||||
let starting_raw_key = MyNMap::storage_n_map_final_key::<Key, _>((1, 3, 3));
|
||||
let iter = MyNMap::iter_from(starting_raw_key);
|
||||
assert_eq!(iter.collect::<Vec<_>>(), vec![((2, 0, 0), 200)]);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn n_map_double_map_identical_key() {
|
||||
sp_io::TestExternalities::default().execute_with(|| {
|
||||
|
||||
Reference in New Issue
Block a user