1#![cfg(feature = "iterator")]
3
4use crate::namespace::Namespace;
5use crate::PrefixBound;
6use cosmwasm_std::{StdError, StdResult, Storage};
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9
10use crate::de::KeyDeserialize;
11use crate::indexes::Index;
12use crate::iter_helpers::{deserialize_kv, deserialize_v};
13use crate::keys::{Prefixer, PrimaryKey};
14use crate::map::Map;
15use crate::prefix::{namespaced_prefix_range, Prefix};
16use crate::{Bound, Path};
17
18pub trait IndexList<T> {
19 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<T>> + '_>;
20}
21
22pub struct IndexedMap<K, T, I> {
24 pk_namespace: Namespace,
25 primary: Map<K, T>,
26 pub idx: I,
29}
30
31impl<'a, K, T, I> IndexedMap<K, T, I>
32where
33 K: PrimaryKey<'a>,
34 T: Serialize + DeserializeOwned + Clone,
35 I: IndexList<T>,
36{
37 pub const fn new(pk_namespace: &'static str, indexes: I) -> Self {
40 IndexedMap {
41 pk_namespace: Namespace::from_static_str(pk_namespace),
42 primary: Map::new(pk_namespace),
43 idx: indexes,
44 }
45 }
46
47 pub fn new_dyn(pk_namespace: impl Into<Namespace>, indexes: I) -> Self {
50 let pk_namespace = pk_namespace.into();
51
52 IndexedMap {
53 pk_namespace: pk_namespace.clone(),
54 primary: Map::new_dyn(pk_namespace),
55 idx: indexes,
56 }
57 }
58
59 pub fn key(&self, k: K) -> Path<T> {
60 self.primary.key(k)
61 }
62}
63
64impl<'a, K, T, I> IndexedMap<K, T, I>
65where
66 K: PrimaryKey<'a>,
67 T: Serialize + DeserializeOwned + Clone,
68 I: IndexList<T>,
69{
70 pub fn save(&self, store: &mut dyn Storage, key: K, data: &T) -> StdResult<()> {
74 let old_data = self.may_load(store, key.clone())?;
75 self.replace(store, key, Some(data), old_data.as_ref())
76 }
77
78 pub fn remove(&self, store: &mut dyn Storage, key: K) -> StdResult<()> {
79 let old_data = self.may_load(store, key.clone())?;
80 self.replace(store, key, None, old_data.as_ref())
81 }
82
83 pub fn replace(
87 &self,
88 store: &mut dyn Storage,
89 key: K,
90 data: Option<&T>,
91 old_data: Option<&T>,
92 ) -> StdResult<()> {
93 let pk = key.joined_key();
95 if let Some(old) = old_data {
96 for index in self.idx.get_indexes() {
97 index.remove(store, &pk, old)?;
98 }
99 }
100 if let Some(updated) = data {
101 for index in self.idx.get_indexes() {
102 index.save(store, &pk, updated)?;
103 }
104 self.primary.save(store, key, updated)?;
105 } else {
106 self.primary.remove(store, key);
107 }
108 Ok(())
109 }
110
111 pub fn update<A, E>(&self, store: &mut dyn Storage, key: K, action: A) -> Result<T, E>
116 where
117 A: FnOnce(Option<T>) -> Result<T, E>,
118 E: From<StdError>,
119 {
120 let input = self.may_load(store, key.clone())?;
121 let old_val = input.clone();
122 let output = action(input)?;
123 self.replace(store, key, Some(&output), old_val.as_ref())?;
124 Ok(output)
125 }
126
127 pub fn load(&self, store: &dyn Storage, key: K) -> StdResult<T> {
132 self.primary.load(store, key)
133 }
134
135 pub fn may_load(&self, store: &dyn Storage, key: K) -> StdResult<Option<T>> {
138 self.primary.may_load(store, key)
139 }
140
141 pub fn has(&self, store: &dyn Storage, k: K) -> bool {
143 self.primary.key(k).has(store)
144 }
145
146 fn no_prefix_raw(&self) -> Prefix<Vec<u8>, T, K> {
148 Prefix::new(self.pk_namespace.as_slice(), &[])
149 }
150
151 pub fn clear(&self, store: &mut dyn Storage) {
153 const TAKE: usize = 10;
154 let mut cleared = false;
155
156 while !cleared {
157 let paths = self
158 .no_prefix_raw()
159 .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
160 .map(|raw_key| Path::<T>::new(self.pk_namespace.as_slice(), &[raw_key.as_slice()]))
161 .take(TAKE)
163 .collect::<Vec<_>>();
164
165 paths.iter().for_each(|path| store.remove(path));
166
167 cleared = paths.len() < TAKE;
168 }
169 }
170
171 pub fn is_empty(&self, store: &dyn Storage) -> bool {
173 self.no_prefix_raw()
174 .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
175 .next()
176 .is_none()
177 }
178}
179
180#[cfg(feature = "iterator")]
181impl<'a, K, T, I> IndexedMap<K, T, I>
182where
183 K: PrimaryKey<'a>,
184 T: Serialize + DeserializeOwned + Clone,
185 I: IndexList<T>,
186{
187 pub fn prefix_range_raw<'c>(
193 &self,
194 store: &'c dyn Storage,
195 min: Option<PrefixBound<'a, K::Prefix>>,
196 max: Option<PrefixBound<'a, K::Prefix>>,
197 order: cosmwasm_std::Order,
198 ) -> Box<dyn Iterator<Item = StdResult<cosmwasm_std::Record<T>>> + 'c>
199 where
200 T: 'c,
201 'a: 'c,
202 {
203 let mapped = namespaced_prefix_range(store, self.pk_namespace.as_slice(), min, max, order)
204 .map(deserialize_v);
205 Box::new(mapped)
206 }
207}
208
209#[cfg(feature = "iterator")]
210impl<'a, K, T, I> IndexedMap<K, T, I>
211where
212 T: Serialize + DeserializeOwned + Clone,
213 K: PrimaryKey<'a>,
214 I: IndexList<T>,
215{
216 pub fn sub_prefix(&self, p: K::SubPrefix) -> Prefix<K::SuperSuffix, T, K::SuperSuffix> {
217 Prefix::new(self.pk_namespace.as_slice(), &p.prefix())
218 }
219
220 pub fn prefix(&self, p: K::Prefix) -> Prefix<K::Suffix, T, K::Suffix> {
221 Prefix::new(self.pk_namespace.as_slice(), &p.prefix())
222 }
223}
224
225#[cfg(feature = "iterator")]
226impl<'a, K, T, I> IndexedMap<K, T, I>
227where
228 T: Serialize + DeserializeOwned + Clone,
229 K: PrimaryKey<'a> + KeyDeserialize,
230 I: IndexList<T>,
231{
232 pub fn prefix_range<'c>(
239 &self,
240 store: &'c dyn Storage,
241 min: Option<PrefixBound<'a, K::Prefix>>,
242 max: Option<PrefixBound<'a, K::Prefix>>,
243 order: cosmwasm_std::Order,
244 ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'c>
245 where
246 T: 'c,
247 'a: 'c,
248 K: 'c,
249 K::Output: 'static,
250 {
251 let mapped = namespaced_prefix_range(store, self.pk_namespace.as_slice(), min, max, order)
252 .map(deserialize_kv::<K, T>);
253 Box::new(mapped)
254 }
255
256 pub fn range_raw<'c>(
257 &self,
258 store: &'c dyn Storage,
259 min: Option<Bound<'a, K>>,
260 max: Option<Bound<'a, K>>,
261 order: cosmwasm_std::Order,
262 ) -> Box<dyn Iterator<Item = StdResult<cosmwasm_std::Record<T>>> + 'c>
263 where
264 T: 'c,
265 {
266 self.no_prefix_raw().range_raw(store, min, max, order)
267 }
268
269 pub fn keys_raw<'c>(
270 &self,
271 store: &'c dyn Storage,
272 min: Option<Bound<'a, K>>,
273 max: Option<Bound<'a, K>>,
274 order: cosmwasm_std::Order,
275 ) -> Box<dyn Iterator<Item = Vec<u8>> + 'c> {
276 self.no_prefix_raw().keys_raw(store, min, max, order)
277 }
278
279 pub fn range<'c>(
280 &self,
281 store: &'c dyn Storage,
282 min: Option<Bound<'a, K>>,
283 max: Option<Bound<'a, K>>,
284 order: cosmwasm_std::Order,
285 ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'c>
286 where
287 T: 'c,
288 K::Output: 'static,
289 {
290 self.no_prefix().range(store, min, max, order)
291 }
292
293 pub fn keys<'c>(
294 &self,
295 store: &'c dyn Storage,
296 min: Option<Bound<'a, K>>,
297 max: Option<Bound<'a, K>>,
298 order: cosmwasm_std::Order,
299 ) -> Box<dyn Iterator<Item = StdResult<K::Output>> + 'c>
300 where
301 T: 'c,
302 K::Output: 'static,
303 {
304 self.no_prefix().keys(store, min, max, order)
305 }
306
307 fn no_prefix(&self) -> Prefix<K, T, K> {
308 Prefix::new(self.pk_namespace.as_slice(), &[])
309 }
310}
311
312#[cfg(test)]
313mod test {
314
315 use super::*;
316
317 use crate::indexes::test::{index_string_tuple, index_tuple};
318 use crate::{MultiIndex, UniqueIndex};
319 use cosmwasm_std::testing::MockStorage;
320 use cosmwasm_std::Order;
321 use serde::{Deserialize, Serialize};
322
323 #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
324 struct Data {
325 pub name: String,
326 pub last_name: String,
327 pub age: u32,
328 }
329
330 struct DataIndexes<'a> {
331 pub name: MultiIndex<'a, String, Data, String>,
333 pub age: UniqueIndex<'a, u32, Data, String>,
334 pub name_lastname: UniqueIndex<'a, (Vec<u8>, Vec<u8>), Data, String>,
335 }
336
337 impl IndexList<Data> for DataIndexes<'_> {
339 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
340 let v: Vec<&dyn Index<Data>> = vec![&self.name, &self.age, &self.name_lastname];
341 Box::new(v.into_iter())
342 }
343 }
344
345 struct DataCompositeMultiIndex<'a> {
347 pub name_age: MultiIndex<'a, (Vec<u8>, u32), Data, String>,
349 }
350
351 impl IndexList<Data> for DataCompositeMultiIndex<'_> {
353 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
354 let v: Vec<&dyn Index<Data>> = vec![&self.name_age];
355 Box::new(v.into_iter())
356 }
357 }
358
359 const DATA: IndexedMap<&str, Data, DataIndexes> = IndexedMap::new(
360 "data",
361 DataIndexes {
362 name: MultiIndex::new(|_pk, d| d.name.clone(), "data", "data__name"),
363 age: UniqueIndex::new(|d| d.age, "data__age"),
364 name_lastname: UniqueIndex::new(
365 |d| index_string_tuple(&d.name, &d.last_name),
366 "data__name_lastname",
367 ),
368 },
369 );
370
371 fn save_data<'a>(store: &mut MockStorage) -> (Vec<&'a str>, Vec<Data>) {
372 let mut pks = vec![];
373 let mut datas = vec![];
374 let data = Data {
375 name: "Maria".to_string(),
376 last_name: "Doe".to_string(),
377 age: 42,
378 };
379 let pk = "1";
380 DATA.save(store, pk, &data).unwrap();
381 pks.push(pk);
382 datas.push(data);
383
384 let data = Data {
386 name: "Maria".to_string(),
387 last_name: "Williams".to_string(),
388 age: 23,
389 };
390 let pk = "2";
391 DATA.save(store, pk, &data).unwrap();
392 pks.push(pk);
393 datas.push(data);
394
395 let data = Data {
397 name: "John".to_string(),
398 last_name: "Wayne".to_string(),
399 age: 32,
400 };
401 let pk = "3";
402 DATA.save(store, pk, &data).unwrap();
403 pks.push(pk);
404 datas.push(data);
405
406 let data = Data {
407 name: "Maria Luisa".to_string(),
408 last_name: "Rodriguez".to_string(),
409 age: 12,
410 };
411 let pk = "4";
412 DATA.save(store, pk, &data).unwrap();
413 pks.push(pk);
414 datas.push(data);
415
416 let data = Data {
417 name: "Marta".to_string(),
418 last_name: "After".to_string(),
419 age: 90,
420 };
421 let pk = "5";
422 DATA.save(store, pk, &data).unwrap();
423 pks.push(pk);
424 datas.push(data);
425
426 (pks, datas)
427 }
428
429 #[test]
430 fn store_and_load_by_index() {
431 let mut store = MockStorage::new();
432
433 let (pks, datas) = save_data(&mut store);
435 let pk = pks[0];
436 let data = &datas[0];
437
438 let loaded = DATA.load(&store, pk).unwrap();
440 assert_eq!(*data, loaded);
441
442 let count = DATA
443 .idx
444 .name
445 .prefix("Maria".to_string())
446 .range_raw(&store, None, None, Order::Ascending)
447 .count();
448 assert_eq!(2, count);
449
450 let marias: Vec<_> = DATA
452 .idx
453 .name
454 .prefix("Maria".to_string())
455 .range_raw(&store, None, None, Order::Ascending)
456 .collect::<StdResult<_>>()
457 .unwrap();
458 assert_eq!(2, marias.len());
459 let (k, v) = &marias[0];
460 assert_eq!(pk, String::from_slice(k).unwrap());
461 assert_eq!(data, v);
462
463 let count = DATA
465 .idx
466 .name
467 .prefix("Marib".to_string())
468 .range_raw(&store, None, None, Order::Ascending)
469 .count();
470 assert_eq!(0, count);
471
472 let count = DATA
474 .idx
475 .name
476 .prefix("Mari`".to_string())
477 .range_raw(&store, None, None, Order::Ascending)
478 .count();
479 assert_eq!(0, count);
480
481 let count = DATA
483 .idx
484 .name
485 .prefix("Maria5".to_string())
486 .range_raw(&store, None, None, Order::Ascending)
487 .count();
488 assert_eq!(0, count);
489
490 let key = ("Maria".to_string(), "".to_string());
493 let marias = DATA
495 .idx
496 .name
497 .range_raw(&store, Some(Bound::inclusive(key)), None, Order::Ascending)
498 .collect::<StdResult<Vec<_>>>()
499 .unwrap();
500 assert_eq!(4, marias.len());
502
503 let key = "Maria".to_string();
505 let marias2 = DATA
506 .idx
507 .name
508 .prefix_range_raw(
509 &store,
510 Some(PrefixBound::inclusive(key)),
511 None,
512 Order::Ascending,
513 )
514 .collect::<StdResult<Vec<_>>>()
515 .unwrap();
516 assert_eq!(4, marias2.len());
517 assert_eq!(marias, marias2);
518
519 let key = ("Maria".to_string(), "1".to_string());
521 let count = DATA
524 .idx
525 .name
526 .range_raw(&store, Some(Bound::exclusive(key)), None, Order::Ascending)
527 .count();
528 assert_eq!(3, count);
530
531 let age_key = 23u32;
533 let count = DATA
535 .idx
536 .age
537 .range_raw(
538 &store,
539 Some(Bound::inclusive(age_key)),
540 None,
541 Order::Ascending,
542 )
543 .count();
544 assert_eq!(4, count);
546
547 let proper = 42u32;
549 let aged = DATA.idx.age.item(&store, proper).unwrap().unwrap();
550 assert_eq!(pk, String::from_vec(aged.0).unwrap());
551 assert_eq!(*data, aged.1);
552
553 let too_old = 43u32;
555 let aged = DATA.idx.age.item(&store, too_old).unwrap();
556 assert_eq!(None, aged);
557 }
558
559 #[test]
560 fn existence() {
561 let mut store = MockStorage::new();
562 let (pks, _) = save_data(&mut store);
563
564 assert!(DATA.has(&store, pks[0]));
565 assert!(!DATA.has(&store, "6"));
566 }
567
568 #[test]
569 fn range_raw_simple_key_by_multi_index() {
570 let mut store = MockStorage::new();
571
572 let data1 = Data {
574 name: "Maria".to_string(),
575 last_name: "".to_string(),
576 age: 42,
577 };
578 let pk = "5627";
579 DATA.save(&mut store, pk, &data1).unwrap();
580
581 let data2 = Data {
582 name: "Juan".to_string(),
583 last_name: "Perez".to_string(),
584 age: 13,
585 };
586 let pk = "5628";
587 DATA.save(&mut store, pk, &data2).unwrap();
588
589 let data3 = Data {
590 name: "Maria".to_string(),
591 last_name: "Williams".to_string(),
592 age: 24,
593 };
594 let pk = "5629";
595 DATA.save(&mut store, pk, &data3).unwrap();
596
597 let data4 = Data {
598 name: "Maria Luisa".to_string(),
599 last_name: "Bemberg".to_string(),
600 age: 12,
601 };
602 let pk = "5630";
603 DATA.save(&mut store, pk, &data4).unwrap();
604
605 let marias: Vec<_> = DATA
606 .idx
607 .name
608 .prefix("Maria".to_string())
609 .range_raw(&store, None, None, Order::Descending)
610 .collect::<StdResult<_>>()
611 .unwrap();
612 let count = marias.len();
613 assert_eq!(2, count);
614
615 assert_eq!(marias[0].0, b"5629");
617 assert_eq!(marias[1].0, b"5627");
618 assert_eq!(marias[0].1, data3);
620 assert_eq!(marias[1].1, data1);
621 }
622
623 #[test]
624 fn range_simple_key_by_multi_index() {
625 let mut store = MockStorage::new();
626
627 let data1 = Data {
629 name: "Maria".to_string(),
630 last_name: "".to_string(),
631 age: 42,
632 };
633 let pk = "5627";
634 DATA.save(&mut store, pk, &data1).unwrap();
635
636 let data2 = Data {
637 name: "Juan".to_string(),
638 last_name: "Perez".to_string(),
639 age: 13,
640 };
641 let pk = "5628";
642 DATA.save(&mut store, pk, &data2).unwrap();
643
644 let data3 = Data {
645 name: "Maria".to_string(),
646 last_name: "Williams".to_string(),
647 age: 24,
648 };
649 let pk = "5629";
650 DATA.save(&mut store, pk, &data3).unwrap();
651
652 let data4 = Data {
653 name: "Maria Luisa".to_string(),
654 last_name: "Bemberg".to_string(),
655 age: 12,
656 };
657 let pk = "5630";
658 DATA.save(&mut store, pk, &data4).unwrap();
659
660 let marias: Vec<_> = DATA
661 .idx
662 .name
663 .prefix("Maria".to_string())
664 .range(&store, None, None, Order::Descending)
665 .collect::<StdResult<_>>()
666 .unwrap();
667 let count = marias.len();
668 assert_eq!(2, count);
669
670 assert_eq!(marias[0].0, "5629");
672 assert_eq!(marias[1].0, "5627");
673 assert_eq!(marias[0].1, data3);
675 assert_eq!(marias[1].1, data1);
676 }
677
678 #[test]
679 fn range_raw_composite_key_by_multi_index() {
680 let mut store = MockStorage::new();
681
682 let indexes = DataCompositeMultiIndex {
683 name_age: MultiIndex::new(
684 |_pk, d| index_tuple(&d.name, d.age),
685 "data",
686 "data__name_age",
687 ),
688 };
689 let map = IndexedMap::new("data", indexes);
690
691 let data1 = Data {
693 name: "Maria".to_string(),
694 last_name: "".to_string(),
695 age: 42,
696 };
697 let pk1: &[u8] = b"5627";
698 map.save(&mut store, pk1, &data1).unwrap();
699
700 let data2 = Data {
701 name: "Juan".to_string(),
702 last_name: "Perez".to_string(),
703 age: 13,
704 };
705 let pk2: &[u8] = b"5628";
706 map.save(&mut store, pk2, &data2).unwrap();
707
708 let data3 = Data {
709 name: "Maria".to_string(),
710 last_name: "Young".to_string(),
711 age: 24,
712 };
713 let pk3: &[u8] = b"5629";
714 map.save(&mut store, pk3, &data3).unwrap();
715
716 let data4 = Data {
717 name: "Maria Luisa".to_string(),
718 last_name: "Bemberg".to_string(),
719 age: 43,
720 };
721 let pk4: &[u8] = b"5630";
722 map.save(&mut store, pk4, &data4).unwrap();
723
724 let marias: Vec<_> = map
725 .idx
726 .name_age
727 .sub_prefix(b"Maria".to_vec())
728 .range_raw(&store, None, None, Order::Descending)
729 .collect::<StdResult<_>>()
730 .unwrap();
731 let count = marias.len();
732 assert_eq!(2, count);
733
734 assert_eq!(pk1, marias[0].0);
736 assert_eq!(pk3, marias[1].0);
737
738 assert_eq!(data1, marias[0].1);
740 assert_eq!(data3, marias[1].1);
741 }
742
743 #[test]
744 fn range_composite_key_by_multi_index() {
745 let mut store = MockStorage::new();
746
747 let indexes = DataCompositeMultiIndex {
748 name_age: MultiIndex::new(
749 |_pk, d| index_tuple(&d.name, d.age),
750 "data",
751 "data__name_age",
752 ),
753 };
754 let map = IndexedMap::new("data", indexes);
755
756 let data1 = Data {
758 name: "Maria".to_string(),
759 last_name: "".to_string(),
760 age: 42,
761 };
762 let pk1 = "5627";
763 map.save(&mut store, pk1, &data1).unwrap();
764
765 let data2 = Data {
766 name: "Juan".to_string(),
767 last_name: "Perez".to_string(),
768 age: 13,
769 };
770 let pk2 = "5628";
771 map.save(&mut store, pk2, &data2).unwrap();
772
773 let data3 = Data {
774 name: "Maria".to_string(),
775 last_name: "Young".to_string(),
776 age: 24,
777 };
778 let pk3 = "5629";
779 map.save(&mut store, pk3, &data3).unwrap();
780
781 let data4 = Data {
782 name: "Maria Luisa".to_string(),
783 last_name: "Bemberg".to_string(),
784 age: 43,
785 };
786 let pk4 = "5630";
787 map.save(&mut store, pk4, &data4).unwrap();
788
789 let marias: Vec<_> = map
790 .idx
791 .name_age
792 .sub_prefix(b"Maria".to_vec())
793 .range(&store, None, None, Order::Descending)
794 .collect::<StdResult<_>>()
795 .unwrap();
796 let count = marias.len();
797 assert_eq!(2, count);
798
799 assert_eq!(pk1, marias[0].0);
801 assert_eq!(pk3, marias[1].0);
802
803 assert_eq!(data1, marias[0].1);
805 assert_eq!(data3, marias[1].1);
806 }
807
808 #[test]
809 fn unique_index_enforced() {
810 let mut store = MockStorage::new();
811
812 let (pks, datas) = save_data(&mut store);
814
815 let data5 = Data {
817 name: "Marcel".to_string(),
818 last_name: "Laurens".to_string(),
819 age: 42,
820 };
821 let pk5 = "4";
822
823 DATA.save(&mut store, pk5, &data5).unwrap_err();
825
826 let age42 = 42u32;
829 let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
830 assert_eq!(String::from_vec(k).unwrap(), pks[0]);
831 assert_eq!(v.name, datas[0].name);
832 assert_eq!(v.age, datas[0].age);
833
834 let age23 = 23u32;
836 let (k, v) = DATA.idx.age.item(&store, age23).unwrap().unwrap();
837 assert_eq!(String::from_vec(k).unwrap(), pks[1]);
838 assert_eq!(v.name, datas[1].name);
839 assert_eq!(v.age, datas[1].age);
840
841 DATA.remove(&mut store, pks[0]).unwrap();
843 DATA.save(&mut store, pk5, &data5).unwrap();
844 let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
846 assert_eq!(String::from_vec(k).unwrap(), pk5);
847 assert_eq!(v.name, data5.name);
848 assert_eq!(v.age, data5.age);
849 }
850
851 #[test]
852 fn unique_index_enforced_composite_key() {
853 let mut store = MockStorage::new();
854
855 save_data(&mut store);
857
858 let data5 = Data {
860 name: "Maria".to_string(),
861 last_name: "Doe".to_string(),
862 age: 24,
863 };
864 let pk5 = "5";
865 DATA.save(&mut store, pk5, &data5).unwrap_err();
867 }
868
869 #[test]
870 fn remove_and_update_reflected_on_indexes() {
871 let mut store = MockStorage::new();
872
873 let name_count = |store: &MockStorage, name: &str| -> usize {
874 DATA.idx
875 .name
876 .prefix(name.to_string())
877 .keys_raw(store, None, None, Order::Ascending)
878 .count()
879 };
880
881 let (pks, _) = save_data(&mut store);
883
884 assert_eq!(name_count(&store, "Maria"), 2);
886 assert_eq!(name_count(&store, "John"), 1);
887 assert_eq!(name_count(&store, "Maria Luisa"), 1);
888 assert_eq!(name_count(&store, "Mary"), 0);
889
890 DATA.remove(&mut store, pks[1]).unwrap();
892
893 DATA.update(&mut store, pks[2], |d| -> StdResult<_> {
895 let mut x = d.unwrap();
896 assert_eq!(&x.name, "John");
897 x.name = "Mary".to_string();
898 Ok(x)
899 })
900 .unwrap();
901
902 assert_eq!(name_count(&store, "Maria"), 1);
904 assert_eq!(name_count(&store, "Maria Luisa"), 1);
905 assert_eq!(name_count(&store, "John"), 0);
906 assert_eq!(name_count(&store, "Mary"), 1);
907 }
908
909 #[test]
910 fn range_raw_simple_key_by_unique_index() {
911 let mut store = MockStorage::new();
912
913 let (pks, datas) = save_data(&mut store);
915
916 let res: StdResult<Vec<_>> = DATA
917 .idx
918 .age
919 .range_raw(&store, None, None, Order::Ascending)
920 .collect();
921 let ages = res.unwrap();
922
923 let count = ages.len();
924 assert_eq!(5, count);
925
926 assert_eq!(pks[3], String::from_slice(&ages[0].0).unwrap()); assert_eq!(pks[1], String::from_slice(&ages[1].0).unwrap()); assert_eq!(pks[2], String::from_slice(&ages[2].0).unwrap()); assert_eq!(pks[0], String::from_slice(&ages[3].0).unwrap()); assert_eq!(pks[4], String::from_slice(&ages[4].0).unwrap()); assert_eq!(datas[3], ages[0].1);
935 assert_eq!(datas[1], ages[1].1);
936 assert_eq!(datas[2], ages[2].1);
937 assert_eq!(datas[0], ages[3].1);
938 assert_eq!(datas[4], ages[4].1);
939 }
940
941 #[test]
942 fn range_simple_key_by_unique_index() {
943 let mut store = MockStorage::new();
944
945 let (pks, datas) = save_data(&mut store);
947
948 let res: StdResult<Vec<_>> = DATA
949 .idx
950 .age
951 .range(&store, None, None, Order::Ascending)
952 .collect();
953 let ages = res.unwrap();
954
955 let count = ages.len();
956 assert_eq!(5, count);
957
958 assert_eq!(pks[3], ages[0].0);
960 assert_eq!(pks[1], ages[1].0);
961 assert_eq!(pks[2], ages[2].0);
962 assert_eq!(pks[0], ages[3].0);
963 assert_eq!(pks[4], ages[4].0);
964
965 assert_eq!(datas[3], ages[0].1);
967 assert_eq!(datas[1], ages[1].1);
968 assert_eq!(datas[2], ages[2].1);
969 assert_eq!(datas[0], ages[3].1);
970 assert_eq!(datas[4], ages[4].1);
971 }
972
973 #[test]
974 fn range_raw_composite_key_by_unique_index() {
975 let mut store = MockStorage::new();
976
977 let (pks, datas) = save_data(&mut store);
979
980 let res: StdResult<Vec<_>> = DATA
981 .idx
982 .name_lastname
983 .prefix(b"Maria".to_vec())
984 .range_raw(&store, None, None, Order::Ascending)
985 .collect();
986 let marias = res.unwrap();
987
988 let count = marias.len();
990 assert_eq!(2, count);
991
992 assert_eq!(pks[0], String::from_slice(&marias[0].0).unwrap());
994 assert_eq!(pks[1], String::from_slice(&marias[1].0).unwrap());
995
996 assert_eq!(datas[0], marias[0].1);
998 assert_eq!(datas[1], marias[1].1);
999 }
1000
1001 #[test]
1002 fn range_composite_key_by_unique_index() {
1003 let mut store = MockStorage::new();
1004
1005 let (pks, datas) = save_data(&mut store);
1007
1008 let res: StdResult<Vec<_>> = DATA
1009 .idx
1010 .name_lastname
1011 .prefix(b"Maria".to_vec())
1012 .range(&store, None, None, Order::Ascending)
1013 .collect();
1014 let marias = res.unwrap();
1015
1016 let count = marias.len();
1018 assert_eq!(2, count);
1019
1020 assert_eq!(pks[0], marias[0].0);
1022 assert_eq!(pks[1], marias[1].0);
1023
1024 assert_eq!(datas[0], marias[0].1);
1026 assert_eq!(datas[1], marias[1].1);
1027 }
1028
1029 #[test]
1030 #[cfg(feature = "iterator")]
1031 fn range_simple_string_key() {
1032 let mut store = MockStorage::new();
1033
1034 let (pks, datas) = save_data(&mut store);
1036
1037 let all: StdResult<Vec<_>> = DATA.range(&store, None, None, Order::Ascending).collect();
1039 let all = all.unwrap();
1040 assert_eq!(
1041 all,
1042 pks.clone()
1043 .into_iter()
1044 .map(str::to_string)
1045 .zip(datas.clone().into_iter())
1046 .collect::<Vec<_>>()
1047 );
1048
1049 let all: StdResult<Vec<_>> = DATA
1051 .range(&store, Some(Bound::inclusive("3")), None, Order::Ascending)
1052 .collect();
1053 let all = all.unwrap();
1054 assert_eq!(
1055 all,
1056 pks.into_iter()
1057 .map(str::to_string)
1058 .zip(datas.into_iter())
1059 .rev()
1060 .take(3)
1061 .rev()
1062 .collect::<Vec<_>>()
1063 );
1064 }
1065
1066 #[test]
1067 #[cfg(feature = "iterator")]
1068 fn prefix_simple_string_key() {
1069 let mut store = MockStorage::new();
1070
1071 let (pks, datas) = save_data(&mut store);
1073
1074 let all: StdResult<Vec<_>> = DATA
1078 .prefix(())
1079 .range(&store, None, None, Order::Ascending)
1080 .collect();
1081 let all = all.unwrap();
1082 assert_eq!(
1083 all,
1084 pks.clone()
1085 .into_iter()
1086 .map(str::to_string)
1087 .zip(datas.into_iter())
1088 .collect::<Vec<_>>()
1089 );
1090 }
1091
1092 #[test]
1093 #[cfg(feature = "iterator")]
1094 fn prefix_composite_key() {
1095 let mut store = MockStorage::new();
1096
1097 let indexes = DataCompositeMultiIndex {
1098 name_age: MultiIndex::new(
1099 |_pk, d| index_tuple(&d.name, d.age),
1100 "data",
1101 "data__name_age",
1102 ),
1103 };
1104 let map = IndexedMap::new("data", indexes);
1105
1106 let data1 = Data {
1108 name: "Maria".to_string(),
1109 last_name: "".to_string(),
1110 age: 42,
1111 };
1112 let pk1 = ("1", "5627");
1113 map.save(&mut store, pk1, &data1).unwrap();
1114
1115 let data2 = Data {
1116 name: "Juan".to_string(),
1117 last_name: "Perez".to_string(),
1118 age: 13,
1119 };
1120 let pk2 = ("2", "5628");
1121 map.save(&mut store, pk2, &data2).unwrap();
1122
1123 let data3 = Data {
1124 name: "Maria".to_string(),
1125 last_name: "Young".to_string(),
1126 age: 24,
1127 };
1128 let pk3 = ("2", "5629");
1129 map.save(&mut store, pk3, &data3).unwrap();
1130
1131 let data4 = Data {
1132 name: "Maria Luisa".to_string(),
1133 last_name: "Bemberg".to_string(),
1134 age: 43,
1135 };
1136 let pk4 = ("3", "5630");
1137 map.save(&mut store, pk4, &data4).unwrap();
1138
1139 let result: StdResult<Vec<_>> = map
1141 .prefix("2")
1142 .range(&store, None, None, Order::Ascending)
1143 .collect();
1144 let result = result.unwrap();
1145 assert_eq!(
1146 result,
1147 [("5628".to_string(), data2), ("5629".to_string(), data3),]
1148 );
1149 }
1150
1151 #[test]
1152 #[cfg(feature = "iterator")]
1153 fn prefix_triple_key() {
1154 let mut store = MockStorage::new();
1155
1156 let indexes = DataCompositeMultiIndex {
1157 name_age: MultiIndex::new(
1158 |_pk, d| index_tuple(&d.name, d.age),
1159 "data",
1160 "data__name_age",
1161 ),
1162 };
1163 let map = IndexedMap::new("data", indexes);
1164
1165 let data1 = Data {
1167 name: "Maria".to_string(),
1168 last_name: "".to_string(),
1169 age: 42,
1170 };
1171 let pk1 = ("1", "1", "5627");
1172 map.save(&mut store, pk1, &data1).unwrap();
1173
1174 let data2 = Data {
1175 name: "Juan".to_string(),
1176 last_name: "Perez".to_string(),
1177 age: 13,
1178 };
1179 let pk2 = ("1", "2", "5628");
1180 map.save(&mut store, pk2, &data2).unwrap();
1181
1182 let data3 = Data {
1183 name: "Maria".to_string(),
1184 last_name: "Young".to_string(),
1185 age: 24,
1186 };
1187 let pk3 = ("2", "1", "5629");
1188 map.save(&mut store, pk3, &data3).unwrap();
1189
1190 let data4 = Data {
1191 name: "Maria Luisa".to_string(),
1192 last_name: "Bemberg".to_string(),
1193 age: 43,
1194 };
1195 let pk4 = ("2", "2", "5630");
1196 map.save(&mut store, pk4, &data4).unwrap();
1197
1198 let result: StdResult<Vec<_>> = map
1200 .prefix(("1", "2"))
1201 .range(&store, None, None, Order::Ascending)
1202 .collect();
1203 let result = result.unwrap();
1204 assert_eq!(result, [("5628".to_string(), data2),]);
1205 }
1206
1207 #[test]
1208 #[cfg(feature = "iterator")]
1209 fn sub_prefix_triple_key() {
1210 let mut store = MockStorage::new();
1211
1212 let indexes = DataCompositeMultiIndex {
1213 name_age: MultiIndex::new(
1214 |_pk, d| index_tuple(&d.name, d.age),
1215 "data",
1216 "data__name_age",
1217 ),
1218 };
1219 let map = IndexedMap::new("data", indexes);
1220
1221 let data1 = Data {
1223 name: "Maria".to_string(),
1224 last_name: "".to_string(),
1225 age: 42,
1226 };
1227 let pk1 = ("1", "1", "5627");
1228 map.save(&mut store, pk1, &data1).unwrap();
1229
1230 let data2 = Data {
1231 name: "Juan".to_string(),
1232 last_name: "Perez".to_string(),
1233 age: 13,
1234 };
1235 let pk2 = ("1", "2", "5628");
1236 map.save(&mut store, pk2, &data2).unwrap();
1237
1238 let data3 = Data {
1239 name: "Maria".to_string(),
1240 last_name: "Young".to_string(),
1241 age: 24,
1242 };
1243 let pk3 = ("2", "1", "5629");
1244 map.save(&mut store, pk3, &data3).unwrap();
1245
1246 let data4 = Data {
1247 name: "Maria Luisa".to_string(),
1248 last_name: "Bemberg".to_string(),
1249 age: 43,
1250 };
1251 let pk4 = ("2", "2", "5630");
1252 map.save(&mut store, pk4, &data4).unwrap();
1253
1254 let result: StdResult<Vec<_>> = map
1256 .sub_prefix("1")
1257 .range(&store, None, None, Order::Ascending)
1258 .collect();
1259 let result = result.unwrap();
1260 assert_eq!(
1261 result,
1262 [
1263 (("1".to_string(), "5627".to_string()), data1),
1264 (("2".to_string(), "5628".to_string()), data2),
1265 ]
1266 );
1267 }
1268
1269 #[test]
1270 #[cfg(feature = "iterator")]
1271 fn prefix_range_simple_key() {
1272 let mut store = MockStorage::new();
1273
1274 let indexes = DataCompositeMultiIndex {
1275 name_age: MultiIndex::new(
1276 |_pk, d| index_tuple(&d.name, d.age),
1277 "data",
1278 "data__name_age",
1279 ),
1280 };
1281 let map = IndexedMap::new("data", indexes);
1282
1283 let data1 = Data {
1285 name: "Maria".to_string(),
1286 last_name: "".to_string(),
1287 age: 42,
1288 };
1289 let pk1 = ("1", "5627");
1290 map.save(&mut store, pk1, &data1).unwrap();
1291
1292 let data2 = Data {
1293 name: "Juan".to_string(),
1294 last_name: "Perez".to_string(),
1295 age: 13,
1296 };
1297 let pk2 = ("2", "5628");
1298 map.save(&mut store, pk2, &data2).unwrap();
1299
1300 let data3 = Data {
1301 name: "Maria".to_string(),
1302 last_name: "Young".to_string(),
1303 age: 24,
1304 };
1305 let pk3 = ("2", "5629");
1306 map.save(&mut store, pk3, &data3).unwrap();
1307
1308 let data4 = Data {
1309 name: "Maria Luisa".to_string(),
1310 last_name: "Bemberg".to_string(),
1311 age: 43,
1312 };
1313 let pk4 = ("3", "5630");
1314 map.save(&mut store, pk4, &data4).unwrap();
1315
1316 let result: StdResult<Vec<_>> = map
1318 .prefix_range(
1319 &store,
1320 Some(PrefixBound::inclusive("2")),
1321 None,
1322 Order::Ascending,
1323 )
1324 .collect();
1325 let result = result.unwrap();
1326 assert_eq!(
1327 result,
1328 [
1329 (("2".to_string(), "5628".to_string()), data2.clone()),
1330 (("2".to_string(), "5629".to_string()), data3.clone()),
1331 (("3".to_string(), "5630".to_string()), data4)
1332 ]
1333 );
1334
1335 let result: StdResult<Vec<_>> = map
1337 .prefix_range(
1338 &store,
1339 Some(PrefixBound::inclusive("2")),
1340 Some(PrefixBound::exclusive("3")),
1341 Order::Ascending,
1342 )
1343 .collect();
1344 let result = result.unwrap();
1345 assert_eq!(
1346 result,
1347 [
1348 (("2".to_string(), "5628".to_string()), data2),
1349 (("2".to_string(), "5629".to_string()), data3),
1350 ]
1351 );
1352 }
1353
1354 #[test]
1355 #[cfg(feature = "iterator")]
1356 fn prefix_range_triple_key() {
1357 let mut store = MockStorage::new();
1358
1359 let indexes = DataCompositeMultiIndex {
1360 name_age: MultiIndex::new(
1361 |_pk, d| index_tuple(&d.name, d.age),
1362 "data",
1363 "data__name_age",
1364 ),
1365 };
1366 let map = IndexedMap::new("data", indexes);
1367
1368 let data1 = Data {
1370 name: "Maria".to_string(),
1371 last_name: "".to_string(),
1372 age: 42,
1373 };
1374 let pk1 = ("1", "1", "5627");
1375 map.save(&mut store, pk1, &data1).unwrap();
1376
1377 let data2 = Data {
1378 name: "Juan".to_string(),
1379 last_name: "Perez".to_string(),
1380 age: 13,
1381 };
1382 let pk2 = ("1", "2", "5628");
1383 map.save(&mut store, pk2, &data2).unwrap();
1384
1385 let data3 = Data {
1386 name: "Maria".to_string(),
1387 last_name: "Young".to_string(),
1388 age: 24,
1389 };
1390 let pk3 = ("2", "1", "5629");
1391 map.save(&mut store, pk3, &data3).unwrap();
1392
1393 let data4 = Data {
1394 name: "Maria Luisa".to_string(),
1395 last_name: "Bemberg".to_string(),
1396 age: 43,
1397 };
1398 let pk4 = ("2", "2", "5630");
1399 map.save(&mut store, pk4, &data4).unwrap();
1400
1401 let result: StdResult<Vec<_>> = map
1403 .prefix_range(
1404 &store,
1405 Some(PrefixBound::inclusive(("1", "2"))),
1406 None,
1407 Order::Ascending,
1408 )
1409 .collect();
1410 let result = result.unwrap();
1411 assert_eq!(
1412 result,
1413 [
1414 (
1415 ("1".to_string(), "2".to_string(), "5628".to_string()),
1416 data2.clone()
1417 ),
1418 (
1419 ("2".to_string(), "1".to_string(), "5629".to_string()),
1420 data3.clone()
1421 ),
1422 (
1423 ("2".to_string(), "2".to_string(), "5630".to_string()),
1424 data4
1425 )
1426 ]
1427 );
1428
1429 let result: StdResult<Vec<_>> = map
1431 .prefix_range(
1432 &store,
1433 Some(PrefixBound::inclusive(("1", "2"))),
1434 Some(PrefixBound::inclusive(("2", "1"))),
1435 Order::Ascending,
1436 )
1437 .collect();
1438 let result = result.unwrap();
1439 assert_eq!(
1440 result,
1441 [
1442 (
1443 ("1".to_string(), "2".to_string(), "5628".to_string()),
1444 data2
1445 ),
1446 (
1447 ("2".to_string(), "1".to_string(), "5629".to_string()),
1448 data3
1449 ),
1450 ]
1451 );
1452 }
1453
1454 mod bounds_unique_index {
1455 use super::*;
1456
1457 struct Indexes<'a> {
1458 secondary: UniqueIndex<'a, u64, u64, ()>,
1459 }
1460
1461 impl IndexList<u64> for Indexes<'_> {
1462 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1463 let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1464 Box::new(v.into_iter())
1465 }
1466 }
1467
1468 #[test]
1469 #[cfg(feature = "iterator")]
1470 fn composite_key_query() {
1471 let indexes = Indexes {
1472 secondary: UniqueIndex::new(|secondary| *secondary, "test_map__secondary"),
1473 };
1474 let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1475 let mut store = MockStorage::new();
1476
1477 map.save(&mut store, "one", &1).unwrap();
1478 map.save(&mut store, "two", &2).unwrap();
1479 map.save(&mut store, "three", &3).unwrap();
1480
1481 let items: Vec<_> = map
1483 .idx
1484 .secondary
1485 .range_raw(&store, None, Some(Bound::inclusive(1u64)), Order::Ascending)
1486 .collect::<Result<_, _>>()
1487 .unwrap();
1488
1489 let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1491
1492 assert_eq!(items, vec![1]);
1493
1494 let items: Vec<_> = map
1496 .idx
1497 .secondary
1498 .range(&store, Some(Bound::exclusive(2u64)), None, Order::Ascending)
1499 .collect::<Result<_, _>>()
1500 .unwrap();
1501
1502 assert_eq!(items, vec![((), 3)]);
1503 }
1504 }
1505
1506 mod bounds_multi_index {
1507 use super::*;
1508
1509 struct Indexes<'a> {
1510 secondary: MultiIndex<'a, u64, u64, &'a str>,
1512 }
1513
1514 impl IndexList<u64> for Indexes<'_> {
1515 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1516 let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1517 Box::new(v.into_iter())
1518 }
1519 }
1520
1521 #[test]
1522 #[cfg(feature = "iterator")]
1523 fn composite_key_query() {
1524 let indexes = Indexes {
1525 secondary: MultiIndex::new(
1526 |_pk, secondary| *secondary,
1527 "test_map",
1528 "test_map__secondary",
1529 ),
1530 };
1531 let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1532 let mut store = MockStorage::new();
1533
1534 map.save(&mut store, "one", &1).unwrap();
1535 map.save(&mut store, "two", &2).unwrap();
1536 map.save(&mut store, "two2", &2).unwrap();
1537 map.save(&mut store, "three", &3).unwrap();
1538
1539 let items: Vec<_> = map
1541 .idx
1542 .secondary
1543 .prefix_range_raw(
1544 &store,
1545 None,
1546 Some(PrefixBound::inclusive(1u64)),
1547 Order::Ascending,
1548 )
1549 .collect::<Result<_, _>>()
1550 .unwrap();
1551
1552 let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1554
1555 assert_eq!(items, vec![1]);
1556
1557 let items: Vec<_> = map
1560 .idx
1561 .secondary
1562 .range(
1563 &store,
1564 Some(Bound::exclusive((2u64, "two"))),
1565 None,
1566 Order::Ascending,
1567 )
1568 .collect::<Result<_, _>>()
1569 .unwrap();
1570
1571 assert_eq!(
1572 items,
1573 vec![("two2".to_string(), 2), ("three".to_string(), 3)]
1574 );
1575 }
1576 }
1577
1578 mod pk_multi_index {
1579 use super::*;
1580 use cosmwasm_std::{Addr, Uint128};
1581
1582 struct Indexes<'a> {
1583 spender: MultiIndex<'a, Addr, Uint128, (Addr, Addr)>,
1585 }
1586
1587 impl IndexList<Uint128> for Indexes<'_> {
1588 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Uint128>> + '_> {
1589 let v: Vec<&dyn Index<Uint128>> = vec![&self.spender];
1590 Box::new(v.into_iter())
1591 }
1592 }
1593
1594 #[test]
1595 #[cfg(feature = "iterator")]
1596 fn pk_based_index() {
1597 fn pk_index(pk: &[u8]) -> Addr {
1598 let (_owner, spender) = <(Addr, Addr)>::from_slice(pk).unwrap(); spender
1600 }
1601
1602 let indexes = Indexes {
1603 spender: MultiIndex::new(
1604 |pk, _allow| pk_index(pk),
1605 "allowances",
1606 "allowances__spender",
1607 ),
1608 };
1609 let map = IndexedMap::<(&Addr, &Addr), Uint128, Indexes>::new("allowances", indexes);
1610 let mut store = MockStorage::new();
1611
1612 map.save(
1613 &mut store,
1614 (&Addr::unchecked("owner1"), &Addr::unchecked("spender1")),
1615 &Uint128::new(11),
1616 )
1617 .unwrap();
1618 map.save(
1619 &mut store,
1620 (&Addr::unchecked("owner1"), &Addr::unchecked("spender2")),
1621 &Uint128::new(12),
1622 )
1623 .unwrap();
1624 map.save(
1625 &mut store,
1626 (&Addr::unchecked("owner2"), &Addr::unchecked("spender1")),
1627 &Uint128::new(21),
1628 )
1629 .unwrap();
1630
1631 let items: Vec<_> = map
1633 .range_raw(&store, None, None, Order::Ascending)
1634 .collect::<Result<_, _>>()
1635 .unwrap();
1636
1637 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1639
1640 assert_eq!(items, vec![11, 12, 21]);
1641
1642 let items: Vec<_> = map
1644 .idx
1645 .spender
1646 .range_raw(&store, None, None, Order::Ascending)
1647 .collect::<Result<_, _>>()
1648 .unwrap();
1649
1650 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1652
1653 assert_eq!(items, vec![11, 21, 12]);
1654
1655 let items: Vec<_> = map
1657 .prefix(&Addr::unchecked("owner1"))
1658 .range_raw(&store, None, None, Order::Ascending)
1659 .collect::<Result<_, _>>()
1660 .unwrap();
1661
1662 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1664
1665 assert_eq!(items, vec![11, 12]);
1666
1667 let items: Vec<_> = map
1669 .idx
1670 .spender
1671 .prefix(Addr::unchecked("spender1"))
1672 .range_raw(&store, None, None, Order::Ascending)
1673 .collect::<Result<_, _>>()
1674 .unwrap();
1675
1676 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1678
1679 assert_eq!(items, vec![11, 21]);
1680
1681 let items: Vec<_> = map
1683 .idx
1684 .spender
1685 .prefix(Addr::unchecked("spender2"))
1686 .range(&store, None, None, Order::Ascending)
1687 .collect::<Result<_, _>>()
1688 .unwrap();
1689
1690 assert_eq!(
1691 items,
1692 vec![(
1693 (Addr::unchecked("owner1"), Addr::unchecked("spender2")),
1694 Uint128::new(12)
1695 )]
1696 );
1697 }
1698 }
1699
1700 #[test]
1701 fn clear_works() {
1702 let mut storage = MockStorage::new();
1703 let (pks, _) = save_data(&mut storage);
1704
1705 DATA.clear(&mut storage);
1706
1707 for key in pks {
1708 assert!(!DATA.has(&storage, key));
1709 }
1710 }
1711
1712 #[test]
1713 fn is_empty_works() {
1714 let mut storage = MockStorage::new();
1715
1716 assert!(DATA.is_empty(&storage));
1717
1718 save_data(&mut storage);
1719
1720 assert!(!DATA.is_empty(&storage));
1721 }
1722}