diff --git a/src/indexed_map.rs b/src/indexed_map.rs index 5247742..665a3b1 100644 --- a/src/indexed_map.rs +++ b/src/indexed_map.rs @@ -149,23 +149,36 @@ where } /// Clears the map, removing all elements. - pub fn clear(&self, store: &mut dyn Storage) { + pub fn clear(&self, store: &mut dyn Storage) -> StdResult<()> { const TAKE: usize = 10; let mut cleared = false; while !cleared { - let paths = self + let entries = self .no_prefix_raw() - .keys_raw(store, None, None, cosmwasm_std::Order::Ascending) - .map(|raw_key| Path::::new(self.pk_namespace.as_slice(), &[raw_key.as_slice()])) + .range_raw(store, None, None, cosmwasm_std::Order::Ascending) // Take just TAKE elements to prevent possible heap overflow if the Map is big. .take(TAKE) - .collect::>(); - - paths.iter().for_each(|path| store.remove(path)); - - cleared = paths.len() < TAKE; + .collect::, _>>(); + + match entries { + Ok(entries) => { + // Remove from indexes first + for (raw_key, data) in &entries { + for index in self.idx.get_indexes() { + index.remove(store, raw_key, data)?; + } + let path = + Path::::new(self.pk_namespace.as_slice(), &[raw_key.as_slice()]); + store.remove(&path); + } + + cleared = entries.len() < TAKE; + } + Err(e) => return Err(e), + } } + Ok(()) } /// Returns `true` if the map is empty. @@ -1702,13 +1715,48 @@ mod test { let mut storage = MockStorage::new(); let (pks, _) = save_data(&mut storage); - DATA.clear(&mut storage); + DATA.clear(&mut storage).unwrap(); for key in pks { assert!(!DATA.has(&storage, key)); } } + #[test] + fn clear_with_indexes_works() { + let mut storage = MockStorage::new(); + let (pks, _) = save_data(&mut storage); + + DATA.clear(&mut storage).unwrap(); + + for key in pks { + assert!(!DATA.has(&storage, key)); + } + + assert!(DATA.is_empty(&storage), "indexed map should be empty"); + + let count = DATA + .idx + .age + .keys_raw(&storage, None, None, Order::Ascending) + .count(); + assert_eq!(count, 0, "age index should be empty"); + + let count = DATA + .idx + .name + .keys_raw(&storage, None, None, Order::Ascending) + .count(); + assert_eq!(count, 0, "name index should be empty"); + + let count = DATA + .idx + .name_lastname + .keys_raw(&storage, None, None, Order::Ascending) + .count(); + assert_eq!(count, 0, "name_lastname index should be empty"); + } + #[test] fn is_empty_works() { let mut storage = MockStorage::new();