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 use super::*;
315
316 use crate::indexes::test::{index_string_tuple, index_tuple};
317 use crate::{MultiIndex, UniqueIndex};
318 use cosmwasm_std::testing::MockStorage;
319 use cosmwasm_std::{MemoryStorage, Order};
320 use serde::{Deserialize, Serialize};
321
322 #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
323 struct Data {
324 pub name: String,
325 pub last_name: String,
326 pub age: u32,
327 }
328
329 struct DataIndexes<'a> {
330 pub name: MultiIndex<'a, String, Data, String>,
332 pub age: UniqueIndex<'a, u32, Data, String>,
333 pub name_lastname: UniqueIndex<'a, (Vec<u8>, Vec<u8>), Data, String>,
334 }
335
336 impl<'a> IndexList<Data> for DataIndexes<'a> {
338 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
339 let v: Vec<&dyn Index<Data>> = vec![&self.name, &self.age, &self.name_lastname];
340 Box::new(v.into_iter())
341 }
342 }
343
344 struct DataCompositeMultiIndex<'a> {
346 pub name_age: MultiIndex<'a, (Vec<u8>, u32), Data, String>,
348 }
349
350 impl<'a> IndexList<Data> for DataCompositeMultiIndex<'a> {
352 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
353 let v: Vec<&dyn Index<Data>> = vec![&self.name_age];
354 Box::new(v.into_iter())
355 }
356 }
357
358 const DATA: IndexedMap<&str, Data, DataIndexes> = IndexedMap::new(
359 "data",
360 DataIndexes {
361 name: MultiIndex::new(|_pk, d| d.name.clone(), "data", "data__name"),
362 age: UniqueIndex::new(|d| d.age, "data__age"),
363 name_lastname: UniqueIndex::new(
364 |d| index_string_tuple(&d.name, &d.last_name),
365 "data__name_lastname",
366 ),
367 },
368 );
369
370 fn save_data<'a>(store: &mut MockStorage) -> (Vec<&'a str>, Vec<Data>) {
371 let mut pks = vec![];
372 let mut datas = vec![];
373 let data = Data {
374 name: "Maria".to_string(),
375 last_name: "Doe".to_string(),
376 age: 42,
377 };
378 let pk = "1";
379 DATA.save(store, pk, &data).unwrap();
380 pks.push(pk);
381 datas.push(data);
382
383 let data = Data {
385 name: "Maria".to_string(),
386 last_name: "Williams".to_string(),
387 age: 23,
388 };
389 let pk = "2";
390 DATA.save(store, pk, &data).unwrap();
391 pks.push(pk);
392 datas.push(data);
393
394 let data = Data {
396 name: "John".to_string(),
397 last_name: "Wayne".to_string(),
398 age: 32,
399 };
400 let pk = "3";
401 DATA.save(store, pk, &data).unwrap();
402 pks.push(pk);
403 datas.push(data);
404
405 let data = Data {
406 name: "Maria Luisa".to_string(),
407 last_name: "Rodriguez".to_string(),
408 age: 12,
409 };
410 let pk = "4";
411 DATA.save(store, pk, &data).unwrap();
412 pks.push(pk);
413 datas.push(data);
414
415 let data = Data {
416 name: "Marta".to_string(),
417 last_name: "After".to_string(),
418 age: 90,
419 };
420 let pk = "5";
421 DATA.save(store, pk, &data).unwrap();
422 pks.push(pk);
423 datas.push(data);
424
425 (pks, datas)
426 }
427
428 #[test]
429 fn store_and_load_by_index() {
430 let mut store = MockStorage::new();
431
432 let (pks, datas) = save_data(&mut store);
434 let pk = pks[0];
435 let data = &datas[0];
436
437 let loaded = DATA.load(&store, pk).unwrap();
439 assert_eq!(*data, loaded);
440
441 let count = DATA
442 .idx
443 .name
444 .prefix("Maria".to_string())
445 .range_raw(&store, None, None, Order::Ascending)
446 .count();
447 assert_eq!(2, count);
448
449 let marias: Vec<_> = DATA
451 .idx
452 .name
453 .prefix("Maria".to_string())
454 .range_raw(&store, None, None, Order::Ascending)
455 .collect::<StdResult<_>>()
456 .unwrap();
457 assert_eq!(2, marias.len());
458 let (k, v) = &marias[0];
459 assert_eq!(pk, String::from_slice(k).unwrap());
460 assert_eq!(data, v);
461
462 let count = DATA
464 .idx
465 .name
466 .prefix("Marib".to_string())
467 .range_raw(&store, None, None, Order::Ascending)
468 .count();
469 assert_eq!(0, count);
470
471 let count = DATA
473 .idx
474 .name
475 .prefix("Mari`".to_string())
476 .range_raw(&store, None, None, Order::Ascending)
477 .count();
478 assert_eq!(0, count);
479
480 let count = DATA
482 .idx
483 .name
484 .prefix("Maria5".to_string())
485 .range_raw(&store, None, None, Order::Ascending)
486 .count();
487 assert_eq!(0, count);
488
489 let key = ("Maria".to_string(), "".to_string());
492 let marias = DATA
494 .idx
495 .name
496 .range_raw(&store, Some(Bound::inclusive(key)), None, Order::Ascending)
497 .collect::<StdResult<Vec<_>>>()
498 .unwrap();
499 assert_eq!(4, marias.len());
501
502 let key = "Maria".to_string();
504 let marias2 = DATA
505 .idx
506 .name
507 .prefix_range_raw(
508 &store,
509 Some(PrefixBound::inclusive(key)),
510 None,
511 Order::Ascending,
512 )
513 .collect::<StdResult<Vec<_>>>()
514 .unwrap();
515 assert_eq!(4, marias2.len());
516 assert_eq!(marias, marias2);
517
518 let key = ("Maria".to_string(), "1".to_string());
520 let count = DATA
523 .idx
524 .name
525 .range_raw(&store, Some(Bound::exclusive(key)), None, Order::Ascending)
526 .count();
527 assert_eq!(3, count);
529
530 let age_key = 23u32;
532 let count = DATA
534 .idx
535 .age
536 .range_raw(
537 &store,
538 Some(Bound::inclusive(age_key)),
539 None,
540 Order::Ascending,
541 )
542 .count();
543 assert_eq!(4, count);
545
546 let proper = 42u32;
548 let aged = DATA.idx.age.item(&store, proper).unwrap().unwrap();
549 assert_eq!(pk, String::from_vec(aged.0).unwrap());
550 assert_eq!(*data, aged.1);
551
552 let too_old = 43u32;
554 let aged = DATA.idx.age.item(&store, too_old).unwrap();
555 assert_eq!(None, aged);
556 }
557
558 #[test]
559 fn existence() {
560 let mut store = MockStorage::new();
561 let (pks, _) = save_data(&mut store);
562
563 assert!(DATA.has(&store, pks[0]));
564 assert!(!DATA.has(&store, "6"));
565 }
566
567 #[test]
568 fn range_raw_simple_key_by_multi_index() {
569 let mut store = MockStorage::new();
570
571 let data1 = Data {
573 name: "Maria".to_string(),
574 last_name: "".to_string(),
575 age: 42,
576 };
577 let pk = "5627";
578 DATA.save(&mut store, pk, &data1).unwrap();
579
580 let data2 = Data {
581 name: "Juan".to_string(),
582 last_name: "Perez".to_string(),
583 age: 13,
584 };
585 let pk = "5628";
586 DATA.save(&mut store, pk, &data2).unwrap();
587
588 let data3 = Data {
589 name: "Maria".to_string(),
590 last_name: "Williams".to_string(),
591 age: 24,
592 };
593 let pk = "5629";
594 DATA.save(&mut store, pk, &data3).unwrap();
595
596 let data4 = Data {
597 name: "Maria Luisa".to_string(),
598 last_name: "Bemberg".to_string(),
599 age: 12,
600 };
601 let pk = "5630";
602 DATA.save(&mut store, pk, &data4).unwrap();
603
604 let marias: Vec<_> = DATA
605 .idx
606 .name
607 .prefix("Maria".to_string())
608 .range_raw(&store, None, None, Order::Descending)
609 .collect::<StdResult<_>>()
610 .unwrap();
611 let count = marias.len();
612 assert_eq!(2, count);
613
614 assert_eq!(marias[0].0, b"5629");
616 assert_eq!(marias[1].0, b"5627");
617 assert_eq!(marias[0].1, data3);
619 assert_eq!(marias[1].1, data1);
620 }
621
622 #[test]
623 fn range_simple_key_by_multi_index() {
624 let mut store = MockStorage::new();
625
626 let data1 = Data {
628 name: "Maria".to_string(),
629 last_name: "".to_string(),
630 age: 42,
631 };
632 let pk = "5627";
633 DATA.save(&mut store, pk, &data1).unwrap();
634
635 let data2 = Data {
636 name: "Juan".to_string(),
637 last_name: "Perez".to_string(),
638 age: 13,
639 };
640 let pk = "5628";
641 DATA.save(&mut store, pk, &data2).unwrap();
642
643 let data3 = Data {
644 name: "Maria".to_string(),
645 last_name: "Williams".to_string(),
646 age: 24,
647 };
648 let pk = "5629";
649 DATA.save(&mut store, pk, &data3).unwrap();
650
651 let data4 = Data {
652 name: "Maria Luisa".to_string(),
653 last_name: "Bemberg".to_string(),
654 age: 12,
655 };
656 let pk = "5630";
657 DATA.save(&mut store, pk, &data4).unwrap();
658
659 let marias: Vec<_> = DATA
660 .idx
661 .name
662 .prefix("Maria".to_string())
663 .range(&store, None, None, Order::Descending)
664 .collect::<StdResult<_>>()
665 .unwrap();
666 let count = marias.len();
667 assert_eq!(2, count);
668
669 assert_eq!(marias[0].0, "5629");
671 assert_eq!(marias[1].0, "5627");
672 assert_eq!(marias[0].1, data3);
674 assert_eq!(marias[1].1, data1);
675 }
676
677 #[test]
678 fn range_raw_composite_key_by_multi_index() {
679 let mut store = MockStorage::new();
680
681 let indexes = DataCompositeMultiIndex {
682 name_age: MultiIndex::new(
683 |_pk, d| index_tuple(&d.name, d.age),
684 "data",
685 "data__name_age",
686 ),
687 };
688 let map = IndexedMap::new("data", indexes);
689
690 let data1 = Data {
692 name: "Maria".to_string(),
693 last_name: "".to_string(),
694 age: 42,
695 };
696 let pk1: &[u8] = b"5627";
697 map.save(&mut store, pk1, &data1).unwrap();
698
699 let data2 = Data {
700 name: "Juan".to_string(),
701 last_name: "Perez".to_string(),
702 age: 13,
703 };
704 let pk2: &[u8] = b"5628";
705 map.save(&mut store, pk2, &data2).unwrap();
706
707 let data3 = Data {
708 name: "Maria".to_string(),
709 last_name: "Young".to_string(),
710 age: 24,
711 };
712 let pk3: &[u8] = b"5629";
713 map.save(&mut store, pk3, &data3).unwrap();
714
715 let data4 = Data {
716 name: "Maria Luisa".to_string(),
717 last_name: "Bemberg".to_string(),
718 age: 43,
719 };
720 let pk4: &[u8] = b"5630";
721 map.save(&mut store, pk4, &data4).unwrap();
722
723 let marias: Vec<_> = map
724 .idx
725 .name_age
726 .sub_prefix(b"Maria".to_vec())
727 .range_raw(&store, None, None, Order::Descending)
728 .collect::<StdResult<_>>()
729 .unwrap();
730 let count = marias.len();
731 assert_eq!(2, count);
732
733 assert_eq!(pk1, marias[0].0);
735 assert_eq!(pk3, marias[1].0);
736
737 assert_eq!(data1, marias[0].1);
739 assert_eq!(data3, marias[1].1);
740 }
741
742 #[test]
743 fn range_composite_key_by_multi_index() {
744 let mut store = MockStorage::new();
745
746 let indexes = DataCompositeMultiIndex {
747 name_age: MultiIndex::new(
748 |_pk, d| index_tuple(&d.name, d.age),
749 "data",
750 "data__name_age",
751 ),
752 };
753 let map = IndexedMap::new("data", indexes);
754
755 let data1 = Data {
757 name: "Maria".to_string(),
758 last_name: "".to_string(),
759 age: 42,
760 };
761 let pk1 = "5627";
762 map.save(&mut store, pk1, &data1).unwrap();
763
764 let data2 = Data {
765 name: "Juan".to_string(),
766 last_name: "Perez".to_string(),
767 age: 13,
768 };
769 let pk2 = "5628";
770 map.save(&mut store, pk2, &data2).unwrap();
771
772 let data3 = Data {
773 name: "Maria".to_string(),
774 last_name: "Young".to_string(),
775 age: 24,
776 };
777 let pk3 = "5629";
778 map.save(&mut store, pk3, &data3).unwrap();
779
780 let data4 = Data {
781 name: "Maria Luisa".to_string(),
782 last_name: "Bemberg".to_string(),
783 age: 43,
784 };
785 let pk4 = "5630";
786 map.save(&mut store, pk4, &data4).unwrap();
787
788 let marias: Vec<_> = map
789 .idx
790 .name_age
791 .sub_prefix(b"Maria".to_vec())
792 .range(&store, None, None, Order::Descending)
793 .collect::<StdResult<_>>()
794 .unwrap();
795 let count = marias.len();
796 assert_eq!(2, count);
797
798 assert_eq!(pk1, marias[0].0);
800 assert_eq!(pk3, marias[1].0);
801
802 assert_eq!(data1, marias[0].1);
804 assert_eq!(data3, marias[1].1);
805 }
806
807 #[test]
808 fn unique_index_enforced() {
809 let mut store = MockStorage::new();
810
811 let (pks, datas) = save_data(&mut store);
813
814 let data5 = Data {
816 name: "Marcel".to_string(),
817 last_name: "Laurens".to_string(),
818 age: 42,
819 };
820 let pk5 = "4";
821
822 DATA.save(&mut store, pk5, &data5).unwrap_err();
824
825 let age42 = 42u32;
828 let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
829 assert_eq!(String::from_vec(k).unwrap(), pks[0]);
830 assert_eq!(v.name, datas[0].name);
831 assert_eq!(v.age, datas[0].age);
832
833 let age23 = 23u32;
835 let (k, v) = DATA.idx.age.item(&store, age23).unwrap().unwrap();
836 assert_eq!(String::from_vec(k).unwrap(), pks[1]);
837 assert_eq!(v.name, datas[1].name);
838 assert_eq!(v.age, datas[1].age);
839
840 DATA.remove(&mut store, pks[0]).unwrap();
842 DATA.save(&mut store, pk5, &data5).unwrap();
843 let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
845 assert_eq!(String::from_vec(k).unwrap(), pk5);
846 assert_eq!(v.name, data5.name);
847 assert_eq!(v.age, data5.age);
848 }
849
850 #[test]
851 fn unique_index_enforced_composite_key() {
852 let mut store = MockStorage::new();
853
854 save_data(&mut store);
856
857 let data5 = Data {
859 name: "Maria".to_string(),
860 last_name: "Doe".to_string(),
861 age: 24,
862 };
863 let pk5 = "5";
864 DATA.save(&mut store, pk5, &data5).unwrap_err();
866 }
867
868 #[test]
869 fn remove_and_update_reflected_on_indexes() {
870 let mut store = MockStorage::new();
871
872 let name_count = |store: &MemoryStorage, name: &str| -> usize {
873 DATA.idx
874 .name
875 .prefix(name.to_string())
876 .keys_raw(store, None, None, Order::Ascending)
877 .count()
878 };
879
880 let (pks, _) = save_data(&mut store);
882
883 assert_eq!(name_count(&store, "Maria"), 2);
885 assert_eq!(name_count(&store, "John"), 1);
886 assert_eq!(name_count(&store, "Maria Luisa"), 1);
887 assert_eq!(name_count(&store, "Mary"), 0);
888
889 DATA.remove(&mut store, pks[1]).unwrap();
891
892 DATA.update(&mut store, pks[2], |d| -> StdResult<_> {
894 let mut x = d.unwrap();
895 assert_eq!(&x.name, "John");
896 x.name = "Mary".to_string();
897 Ok(x)
898 })
899 .unwrap();
900
901 assert_eq!(name_count(&store, "Maria"), 1);
903 assert_eq!(name_count(&store, "Maria Luisa"), 1);
904 assert_eq!(name_count(&store, "John"), 0);
905 assert_eq!(name_count(&store, "Mary"), 1);
906 }
907
908 #[test]
909 fn range_raw_simple_key_by_unique_index() {
910 let mut store = MockStorage::new();
911
912 let (pks, datas) = save_data(&mut store);
914
915 let res: StdResult<Vec<_>> = DATA
916 .idx
917 .age
918 .range_raw(&store, None, None, Order::Ascending)
919 .collect();
920 let ages = res.unwrap();
921
922 let count = ages.len();
923 assert_eq!(5, count);
924
925 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);
934 assert_eq!(datas[1], ages[1].1);
935 assert_eq!(datas[2], ages[2].1);
936 assert_eq!(datas[0], ages[3].1);
937 assert_eq!(datas[4], ages[4].1);
938 }
939
940 #[test]
941 fn range_simple_key_by_unique_index() {
942 let mut store = MockStorage::new();
943
944 let (pks, datas) = save_data(&mut store);
946
947 let res: StdResult<Vec<_>> = DATA
948 .idx
949 .age
950 .range(&store, None, None, Order::Ascending)
951 .collect();
952 let ages = res.unwrap();
953
954 let count = ages.len();
955 assert_eq!(5, count);
956
957 assert_eq!(pks[3], ages[0].0);
959 assert_eq!(pks[1], ages[1].0);
960 assert_eq!(pks[2], ages[2].0);
961 assert_eq!(pks[0], ages[3].0);
962 assert_eq!(pks[4], ages[4].0);
963
964 assert_eq!(datas[3], ages[0].1);
966 assert_eq!(datas[1], ages[1].1);
967 assert_eq!(datas[2], ages[2].1);
968 assert_eq!(datas[0], ages[3].1);
969 assert_eq!(datas[4], ages[4].1);
970 }
971
972 #[test]
973 fn range_raw_composite_key_by_unique_index() {
974 let mut store = MockStorage::new();
975
976 let (pks, datas) = save_data(&mut store);
978
979 let res: StdResult<Vec<_>> = DATA
980 .idx
981 .name_lastname
982 .prefix(b"Maria".to_vec())
983 .range_raw(&store, None, None, Order::Ascending)
984 .collect();
985 let marias = res.unwrap();
986
987 let count = marias.len();
989 assert_eq!(2, count);
990
991 assert_eq!(pks[0], String::from_slice(&marias[0].0).unwrap());
993 assert_eq!(pks[1], String::from_slice(&marias[1].0).unwrap());
994
995 assert_eq!(datas[0], marias[0].1);
997 assert_eq!(datas[1], marias[1].1);
998 }
999
1000 #[test]
1001 fn range_composite_key_by_unique_index() {
1002 let mut store = MockStorage::new();
1003
1004 let (pks, datas) = save_data(&mut store);
1006
1007 let res: StdResult<Vec<_>> = DATA
1008 .idx
1009 .name_lastname
1010 .prefix(b"Maria".to_vec())
1011 .range(&store, None, None, Order::Ascending)
1012 .collect();
1013 let marias = res.unwrap();
1014
1015 let count = marias.len();
1017 assert_eq!(2, count);
1018
1019 assert_eq!(pks[0], marias[0].0);
1021 assert_eq!(pks[1], marias[1].0);
1022
1023 assert_eq!(datas[0], marias[0].1);
1025 assert_eq!(datas[1], marias[1].1);
1026 }
1027
1028 #[test]
1029 #[cfg(feature = "iterator")]
1030 fn range_simple_string_key() {
1031 let mut store = MockStorage::new();
1032
1033 let (pks, datas) = save_data(&mut store);
1035
1036 let all: StdResult<Vec<_>> = DATA.range(&store, None, None, Order::Ascending).collect();
1038 let all = all.unwrap();
1039 assert_eq!(
1040 all,
1041 pks.clone()
1042 .into_iter()
1043 .map(str::to_string)
1044 .zip(datas.clone().into_iter())
1045 .collect::<Vec<_>>()
1046 );
1047
1048 let all: StdResult<Vec<_>> = DATA
1050 .range(&store, Some(Bound::inclusive("3")), None, Order::Ascending)
1051 .collect();
1052 let all = all.unwrap();
1053 assert_eq!(
1054 all,
1055 pks.into_iter()
1056 .map(str::to_string)
1057 .zip(datas.into_iter())
1058 .rev()
1059 .take(3)
1060 .rev()
1061 .collect::<Vec<_>>()
1062 );
1063 }
1064
1065 #[test]
1066 #[cfg(feature = "iterator")]
1067 fn prefix_simple_string_key() {
1068 let mut store = MockStorage::new();
1069
1070 let (pks, datas) = save_data(&mut store);
1072
1073 let all: StdResult<Vec<_>> = DATA
1077 .prefix(())
1078 .range(&store, None, None, Order::Ascending)
1079 .collect();
1080 let all = all.unwrap();
1081 assert_eq!(
1082 all,
1083 pks.clone()
1084 .into_iter()
1085 .map(str::to_string)
1086 .zip(datas.into_iter())
1087 .collect::<Vec<_>>()
1088 );
1089 }
1090
1091 #[test]
1092 #[cfg(feature = "iterator")]
1093 fn prefix_composite_key() {
1094 let mut store = MockStorage::new();
1095
1096 let indexes = DataCompositeMultiIndex {
1097 name_age: MultiIndex::new(
1098 |_pk, d| index_tuple(&d.name, d.age),
1099 "data",
1100 "data__name_age",
1101 ),
1102 };
1103 let map = IndexedMap::new("data", indexes);
1104
1105 let data1 = Data {
1107 name: "Maria".to_string(),
1108 last_name: "".to_string(),
1109 age: 42,
1110 };
1111 let pk1 = ("1", "5627");
1112 map.save(&mut store, pk1, &data1).unwrap();
1113
1114 let data2 = Data {
1115 name: "Juan".to_string(),
1116 last_name: "Perez".to_string(),
1117 age: 13,
1118 };
1119 let pk2 = ("2", "5628");
1120 map.save(&mut store, pk2, &data2).unwrap();
1121
1122 let data3 = Data {
1123 name: "Maria".to_string(),
1124 last_name: "Young".to_string(),
1125 age: 24,
1126 };
1127 let pk3 = ("2", "5629");
1128 map.save(&mut store, pk3, &data3).unwrap();
1129
1130 let data4 = Data {
1131 name: "Maria Luisa".to_string(),
1132 last_name: "Bemberg".to_string(),
1133 age: 43,
1134 };
1135 let pk4 = ("3", "5630");
1136 map.save(&mut store, pk4, &data4).unwrap();
1137
1138 let result: StdResult<Vec<_>> = map
1140 .prefix("2")
1141 .range(&store, None, None, Order::Ascending)
1142 .collect();
1143 let result = result.unwrap();
1144 assert_eq!(
1145 result,
1146 [("5628".to_string(), data2), ("5629".to_string(), data3),]
1147 );
1148 }
1149
1150 #[test]
1151 #[cfg(feature = "iterator")]
1152 fn prefix_triple_key() {
1153 let mut store = MockStorage::new();
1154
1155 let indexes = DataCompositeMultiIndex {
1156 name_age: MultiIndex::new(
1157 |_pk, d| index_tuple(&d.name, d.age),
1158 "data",
1159 "data__name_age",
1160 ),
1161 };
1162 let map = IndexedMap::new("data", indexes);
1163
1164 let data1 = Data {
1166 name: "Maria".to_string(),
1167 last_name: "".to_string(),
1168 age: 42,
1169 };
1170 let pk1 = ("1", "1", "5627");
1171 map.save(&mut store, pk1, &data1).unwrap();
1172
1173 let data2 = Data {
1174 name: "Juan".to_string(),
1175 last_name: "Perez".to_string(),
1176 age: 13,
1177 };
1178 let pk2 = ("1", "2", "5628");
1179 map.save(&mut store, pk2, &data2).unwrap();
1180
1181 let data3 = Data {
1182 name: "Maria".to_string(),
1183 last_name: "Young".to_string(),
1184 age: 24,
1185 };
1186 let pk3 = ("2", "1", "5629");
1187 map.save(&mut store, pk3, &data3).unwrap();
1188
1189 let data4 = Data {
1190 name: "Maria Luisa".to_string(),
1191 last_name: "Bemberg".to_string(),
1192 age: 43,
1193 };
1194 let pk4 = ("2", "2", "5630");
1195 map.save(&mut store, pk4, &data4).unwrap();
1196
1197 let result: StdResult<Vec<_>> = map
1199 .prefix(("1", "2"))
1200 .range(&store, None, None, Order::Ascending)
1201 .collect();
1202 let result = result.unwrap();
1203 assert_eq!(result, [("5628".to_string(), data2),]);
1204 }
1205
1206 #[test]
1207 #[cfg(feature = "iterator")]
1208 fn sub_prefix_triple_key() {
1209 let mut store = MockStorage::new();
1210
1211 let indexes = DataCompositeMultiIndex {
1212 name_age: MultiIndex::new(
1213 |_pk, d| index_tuple(&d.name, d.age),
1214 "data",
1215 "data__name_age",
1216 ),
1217 };
1218 let map = IndexedMap::new("data", indexes);
1219
1220 let data1 = Data {
1222 name: "Maria".to_string(),
1223 last_name: "".to_string(),
1224 age: 42,
1225 };
1226 let pk1 = ("1", "1", "5627");
1227 map.save(&mut store, pk1, &data1).unwrap();
1228
1229 let data2 = Data {
1230 name: "Juan".to_string(),
1231 last_name: "Perez".to_string(),
1232 age: 13,
1233 };
1234 let pk2 = ("1", "2", "5628");
1235 map.save(&mut store, pk2, &data2).unwrap();
1236
1237 let data3 = Data {
1238 name: "Maria".to_string(),
1239 last_name: "Young".to_string(),
1240 age: 24,
1241 };
1242 let pk3 = ("2", "1", "5629");
1243 map.save(&mut store, pk3, &data3).unwrap();
1244
1245 let data4 = Data {
1246 name: "Maria Luisa".to_string(),
1247 last_name: "Bemberg".to_string(),
1248 age: 43,
1249 };
1250 let pk4 = ("2", "2", "5630");
1251 map.save(&mut store, pk4, &data4).unwrap();
1252
1253 let result: StdResult<Vec<_>> = map
1255 .sub_prefix("1")
1256 .range(&store, None, None, Order::Ascending)
1257 .collect();
1258 let result = result.unwrap();
1259 assert_eq!(
1260 result,
1261 [
1262 (("1".to_string(), "5627".to_string()), data1),
1263 (("2".to_string(), "5628".to_string()), data2),
1264 ]
1265 );
1266 }
1267
1268 #[test]
1269 #[cfg(feature = "iterator")]
1270 fn prefix_range_simple_key() {
1271 let mut store = MockStorage::new();
1272
1273 let indexes = DataCompositeMultiIndex {
1274 name_age: MultiIndex::new(
1275 |_pk, d| index_tuple(&d.name, d.age),
1276 "data",
1277 "data__name_age",
1278 ),
1279 };
1280 let map = IndexedMap::new("data", indexes);
1281
1282 let data1 = Data {
1284 name: "Maria".to_string(),
1285 last_name: "".to_string(),
1286 age: 42,
1287 };
1288 let pk1 = ("1", "5627");
1289 map.save(&mut store, pk1, &data1).unwrap();
1290
1291 let data2 = Data {
1292 name: "Juan".to_string(),
1293 last_name: "Perez".to_string(),
1294 age: 13,
1295 };
1296 let pk2 = ("2", "5628");
1297 map.save(&mut store, pk2, &data2).unwrap();
1298
1299 let data3 = Data {
1300 name: "Maria".to_string(),
1301 last_name: "Young".to_string(),
1302 age: 24,
1303 };
1304 let pk3 = ("2", "5629");
1305 map.save(&mut store, pk3, &data3).unwrap();
1306
1307 let data4 = Data {
1308 name: "Maria Luisa".to_string(),
1309 last_name: "Bemberg".to_string(),
1310 age: 43,
1311 };
1312 let pk4 = ("3", "5630");
1313 map.save(&mut store, pk4, &data4).unwrap();
1314
1315 let result: StdResult<Vec<_>> = map
1317 .prefix_range(
1318 &store,
1319 Some(PrefixBound::inclusive("2")),
1320 None,
1321 Order::Ascending,
1322 )
1323 .collect();
1324 let result = result.unwrap();
1325 assert_eq!(
1326 result,
1327 [
1328 (("2".to_string(), "5628".to_string()), data2.clone()),
1329 (("2".to_string(), "5629".to_string()), data3.clone()),
1330 (("3".to_string(), "5630".to_string()), data4)
1331 ]
1332 );
1333
1334 let result: StdResult<Vec<_>> = map
1336 .prefix_range(
1337 &store,
1338 Some(PrefixBound::inclusive("2")),
1339 Some(PrefixBound::exclusive("3")),
1340 Order::Ascending,
1341 )
1342 .collect();
1343 let result = result.unwrap();
1344 assert_eq!(
1345 result,
1346 [
1347 (("2".to_string(), "5628".to_string()), data2),
1348 (("2".to_string(), "5629".to_string()), data3),
1349 ]
1350 );
1351 }
1352
1353 #[test]
1354 #[cfg(feature = "iterator")]
1355 fn prefix_range_triple_key() {
1356 let mut store = MockStorage::new();
1357
1358 let indexes = DataCompositeMultiIndex {
1359 name_age: MultiIndex::new(
1360 |_pk, d| index_tuple(&d.name, d.age),
1361 "data",
1362 "data__name_age",
1363 ),
1364 };
1365 let map = IndexedMap::new("data", indexes);
1366
1367 let data1 = Data {
1369 name: "Maria".to_string(),
1370 last_name: "".to_string(),
1371 age: 42,
1372 };
1373 let pk1 = ("1", "1", "5627");
1374 map.save(&mut store, pk1, &data1).unwrap();
1375
1376 let data2 = Data {
1377 name: "Juan".to_string(),
1378 last_name: "Perez".to_string(),
1379 age: 13,
1380 };
1381 let pk2 = ("1", "2", "5628");
1382 map.save(&mut store, pk2, &data2).unwrap();
1383
1384 let data3 = Data {
1385 name: "Maria".to_string(),
1386 last_name: "Young".to_string(),
1387 age: 24,
1388 };
1389 let pk3 = ("2", "1", "5629");
1390 map.save(&mut store, pk3, &data3).unwrap();
1391
1392 let data4 = Data {
1393 name: "Maria Luisa".to_string(),
1394 last_name: "Bemberg".to_string(),
1395 age: 43,
1396 };
1397 let pk4 = ("2", "2", "5630");
1398 map.save(&mut store, pk4, &data4).unwrap();
1399
1400 let result: StdResult<Vec<_>> = map
1402 .prefix_range(
1403 &store,
1404 Some(PrefixBound::inclusive(("1", "2"))),
1405 None,
1406 Order::Ascending,
1407 )
1408 .collect();
1409 let result = result.unwrap();
1410 assert_eq!(
1411 result,
1412 [
1413 (
1414 ("1".to_string(), "2".to_string(), "5628".to_string()),
1415 data2.clone()
1416 ),
1417 (
1418 ("2".to_string(), "1".to_string(), "5629".to_string()),
1419 data3.clone()
1420 ),
1421 (
1422 ("2".to_string(), "2".to_string(), "5630".to_string()),
1423 data4
1424 )
1425 ]
1426 );
1427
1428 let result: StdResult<Vec<_>> = map
1430 .prefix_range(
1431 &store,
1432 Some(PrefixBound::inclusive(("1", "2"))),
1433 Some(PrefixBound::inclusive(("2", "1"))),
1434 Order::Ascending,
1435 )
1436 .collect();
1437 let result = result.unwrap();
1438 assert_eq!(
1439 result,
1440 [
1441 (
1442 ("1".to_string(), "2".to_string(), "5628".to_string()),
1443 data2
1444 ),
1445 (
1446 ("2".to_string(), "1".to_string(), "5629".to_string()),
1447 data3
1448 ),
1449 ]
1450 );
1451 }
1452
1453 mod bounds_unique_index {
1454 use super::*;
1455
1456 struct Indexes<'a> {
1457 secondary: UniqueIndex<'a, u64, u64, ()>,
1458 }
1459
1460 impl<'a> IndexList<u64> for Indexes<'a> {
1461 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1462 let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1463 Box::new(v.into_iter())
1464 }
1465 }
1466
1467 #[test]
1468 #[cfg(feature = "iterator")]
1469 fn composite_key_query() {
1470 let indexes = Indexes {
1471 secondary: UniqueIndex::new(|secondary| *secondary, "test_map__secondary"),
1472 };
1473 let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1474 let mut store = MockStorage::new();
1475
1476 map.save(&mut store, "one", &1).unwrap();
1477 map.save(&mut store, "two", &2).unwrap();
1478 map.save(&mut store, "three", &3).unwrap();
1479
1480 let items: Vec<_> = map
1482 .idx
1483 .secondary
1484 .range_raw(&store, None, Some(Bound::inclusive(1u64)), Order::Ascending)
1485 .collect::<Result<_, _>>()
1486 .unwrap();
1487
1488 let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1490
1491 assert_eq!(items, vec![1]);
1492
1493 let items: Vec<_> = map
1495 .idx
1496 .secondary
1497 .range(&store, Some(Bound::exclusive(2u64)), None, Order::Ascending)
1498 .collect::<Result<_, _>>()
1499 .unwrap();
1500
1501 assert_eq!(items, vec![((), 3)]);
1502 }
1503 }
1504
1505 mod bounds_multi_index {
1506 use super::*;
1507
1508 struct Indexes<'a> {
1509 secondary: MultiIndex<'a, u64, u64, &'a str>,
1511 }
1512
1513 impl<'a> IndexList<u64> for Indexes<'a> {
1514 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1515 let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1516 Box::new(v.into_iter())
1517 }
1518 }
1519
1520 #[test]
1521 #[cfg(feature = "iterator")]
1522 fn composite_key_query() {
1523 let indexes = Indexes {
1524 secondary: MultiIndex::new(
1525 |_pk, secondary| *secondary,
1526 "test_map",
1527 "test_map__secondary",
1528 ),
1529 };
1530 let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1531 let mut store = MockStorage::new();
1532
1533 map.save(&mut store, "one", &1).unwrap();
1534 map.save(&mut store, "two", &2).unwrap();
1535 map.save(&mut store, "two2", &2).unwrap();
1536 map.save(&mut store, "three", &3).unwrap();
1537
1538 let items: Vec<_> = map
1540 .idx
1541 .secondary
1542 .prefix_range_raw(
1543 &store,
1544 None,
1545 Some(PrefixBound::inclusive(1u64)),
1546 Order::Ascending,
1547 )
1548 .collect::<Result<_, _>>()
1549 .unwrap();
1550
1551 let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1553
1554 assert_eq!(items, vec![1]);
1555
1556 let items: Vec<_> = map
1559 .idx
1560 .secondary
1561 .range(
1562 &store,
1563 Some(Bound::exclusive((2u64, "two"))),
1564 None,
1565 Order::Ascending,
1566 )
1567 .collect::<Result<_, _>>()
1568 .unwrap();
1569
1570 assert_eq!(
1571 items,
1572 vec![("two2".to_string(), 2), ("three".to_string(), 3)]
1573 );
1574 }
1575 }
1576
1577 mod pk_multi_index {
1578 use super::*;
1579 use cosmwasm_std::{Addr, Uint128};
1580
1581 struct Indexes<'a> {
1582 spender: MultiIndex<'a, Addr, Uint128, (Addr, Addr)>,
1584 }
1585
1586 impl<'a> IndexList<Uint128> for Indexes<'a> {
1587 fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Uint128>> + '_> {
1588 let v: Vec<&dyn Index<Uint128>> = vec![&self.spender];
1589 Box::new(v.into_iter())
1590 }
1591 }
1592
1593 #[test]
1594 #[cfg(feature = "iterator")]
1595 fn pk_based_index() {
1596 fn pk_index(pk: &[u8]) -> Addr {
1597 let (_owner, spender) = <(Addr, Addr)>::from_slice(pk).unwrap(); spender
1599 }
1600
1601 let indexes = Indexes {
1602 spender: MultiIndex::new(
1603 |pk, _allow| pk_index(pk),
1604 "allowances",
1605 "allowances__spender",
1606 ),
1607 };
1608 let map = IndexedMap::<(&Addr, &Addr), Uint128, Indexes>::new("allowances", indexes);
1609 let mut store = MockStorage::new();
1610
1611 map.save(
1612 &mut store,
1613 (&Addr::unchecked("owner1"), &Addr::unchecked("spender1")),
1614 &Uint128::new(11),
1615 )
1616 .unwrap();
1617 map.save(
1618 &mut store,
1619 (&Addr::unchecked("owner1"), &Addr::unchecked("spender2")),
1620 &Uint128::new(12),
1621 )
1622 .unwrap();
1623 map.save(
1624 &mut store,
1625 (&Addr::unchecked("owner2"), &Addr::unchecked("spender1")),
1626 &Uint128::new(21),
1627 )
1628 .unwrap();
1629
1630 let items: Vec<_> = map
1632 .range_raw(&store, None, None, Order::Ascending)
1633 .collect::<Result<_, _>>()
1634 .unwrap();
1635
1636 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1638
1639 assert_eq!(items, vec![11, 12, 21]);
1640
1641 let items: Vec<_> = map
1643 .idx
1644 .spender
1645 .range_raw(&store, None, None, Order::Ascending)
1646 .collect::<Result<_, _>>()
1647 .unwrap();
1648
1649 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1651
1652 assert_eq!(items, vec![11, 21, 12]);
1653
1654 let items: Vec<_> = map
1656 .prefix(&Addr::unchecked("owner1"))
1657 .range_raw(&store, None, None, Order::Ascending)
1658 .collect::<Result<_, _>>()
1659 .unwrap();
1660
1661 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1663
1664 assert_eq!(items, vec![11, 12]);
1665
1666 let items: Vec<_> = map
1668 .idx
1669 .spender
1670 .prefix(Addr::unchecked("spender1"))
1671 .range_raw(&store, None, None, Order::Ascending)
1672 .collect::<Result<_, _>>()
1673 .unwrap();
1674
1675 let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1677
1678 assert_eq!(items, vec![11, 21]);
1679
1680 let items: Vec<_> = map
1682 .idx
1683 .spender
1684 .prefix(Addr::unchecked("spender2"))
1685 .range(&store, None, None, Order::Ascending)
1686 .collect::<Result<_, _>>()
1687 .unwrap();
1688
1689 assert_eq!(
1690 items,
1691 vec![(
1692 (Addr::unchecked("owner1"), Addr::unchecked("spender2")),
1693 Uint128::new(12)
1694 )]
1695 );
1696 }
1697 }
1698
1699 #[test]
1700 fn clear_works() {
1701 let mut storage = MockStorage::new();
1702 let (pks, _) = save_data(&mut storage);
1703
1704 DATA.clear(&mut storage);
1705
1706 for key in pks {
1707 assert!(!DATA.has(&storage, key));
1708 }
1709 }
1710
1711 #[test]
1712 fn is_empty_works() {
1713 let mut storage = MockStorage::new();
1714
1715 assert!(DATA.is_empty(&storage));
1716
1717 save_data(&mut storage);
1718
1719 assert!(!DATA.is_empty(&storage));
1720 }
1721}