|
1 | 1 | use std::borrow::{Borrow, BorrowMut}; |
2 | | -use std::collections::HashMap; |
| 2 | +use std::collections::{HashMap, HashSet}; |
3 | 3 | use std::ops::{Deref, DerefMut}; |
4 | 4 | use std::sync::Arc; |
5 | 5 |
|
@@ -406,7 +406,11 @@ impl Folder { |
406 | 406 | /// * `Vec<View>`: A vector of `View` objects that includes the parent view and all of its child views. |
407 | 407 | pub fn get_view_recursively(&self, view_id: &str) -> Vec<View> { |
408 | 408 | let txn = self.collab.transact(); |
409 | | - self.body.get_view_recursively_with_txn(&txn, view_id) |
| 409 | + let mut views = vec![]; |
| 410 | + self |
| 411 | + .body |
| 412 | + .get_view_recursively_with_txn(&txn, view_id, &mut HashSet::default(), &mut views); |
| 413 | + views |
410 | 414 | } |
411 | 415 | } |
412 | 416 |
|
@@ -579,36 +583,41 @@ impl FolderBody { |
579 | 583 | self.meta.get_with_txn(txn, FOLDER_WORKSPACE_ID) |
580 | 584 | } |
581 | 585 |
|
582 | | - /// Recursively retrieves all views associated with the provided `view_id` using a transaction. |
| 586 | + /// Recursively retrieves all views associated with the provided `view_id` using a transaction, |
| 587 | + /// adding them to the `accumulated_views` vector. |
583 | 588 | /// |
584 | | - /// The function begins by attempting to retrieve the parent view associated with the `view_id`. |
585 | | - /// If the parent view is not found, an empty vector is returned. |
| 589 | + /// The function begins by attempting to retrieve the view associated with the `view_id`. |
| 590 | + /// If the parent view is not found, the function returns. |
586 | 591 | /// If the parent view is found, the function proceeds to retrieve all of its child views recursively. |
| 592 | + /// The function uses a hash set to keep track of the visited view ids to avoid infinite recursion due |
| 593 | + /// to circular dependency. |
587 | 594 | /// |
588 | | - /// The function finally returns a vector containing the parent view and all of its child views. |
| 595 | + /// At the end of the recursion, `accumulated_views` will contain the parent view and all of its child views. |
589 | 596 | /// The views are clones of the original objects. |
590 | 597 | /// |
591 | 598 | /// # Parameters |
592 | 599 | /// |
593 | 600 | /// * `txn`: A read transaction object which is used to execute the view retrieval. |
594 | 601 | /// * `view_id`: The ID of the parent view. |
595 | | - /// |
596 | | - /// # Returns |
597 | | - /// |
598 | | - /// * `Vec<View>`: A vector of `View` objects that includes the parent view and all of its child views. |
599 | | - pub fn get_view_recursively_with_txn<T: ReadTxn>(&self, txn: &T, view_id: &str) -> Vec<View> { |
| 602 | + /// * `visited`: Hash set containing all the traversed view ids. |
| 603 | + /// * `accumulated_views`: Vector containing all the views that are accumulated during the traversal. |
| 604 | + pub fn get_view_recursively_with_txn<T: ReadTxn>( |
| 605 | + &self, |
| 606 | + txn: &T, |
| 607 | + view_id: &str, |
| 608 | + visited: &mut HashSet<String>, |
| 609 | + accumulated_views: &mut Vec<View>, |
| 610 | + ) { |
| 611 | + if !visited.insert(view_id.to_string()) { |
| 612 | + return; |
| 613 | + } |
600 | 614 | match self.views.get_view_with_txn(txn, view_id) { |
601 | | - None => vec![], |
| 615 | + None => (), |
602 | 616 | Some(parent_view) => { |
603 | | - let mut views = vec![parent_view.as_ref().clone()]; |
604 | | - let child_views = parent_view |
605 | | - .children |
606 | | - .items |
607 | | - .iter() |
608 | | - .flat_map(|child| self.get_view_recursively_with_txn(txn, &child.id)) |
609 | | - .collect::<Vec<_>>(); |
610 | | - views.extend(child_views); |
611 | | - views |
| 617 | + accumulated_views.push(parent_view.as_ref().clone()); |
| 618 | + parent_view.children.items.iter().for_each(|child| { |
| 619 | + self.get_view_recursively_with_txn(txn, &child.id, visited, accumulated_views) |
| 620 | + }) |
612 | 621 | }, |
613 | 622 | } |
614 | 623 | } |
@@ -643,7 +652,14 @@ impl FolderBody { |
643 | 652 | .map(|view| view.as_ref().clone()) |
644 | 653 | .collect::<Vec<View>>(); |
645 | 654 | for view in self.views.get_views_belong_to(txn, workspace_id) { |
646 | | - views.extend(self.get_view_recursively_with_txn(txn, &view.id)); |
| 655 | + let mut all_views_in_workspace = vec![]; |
| 656 | + self.get_view_recursively_with_txn( |
| 657 | + txn, |
| 658 | + &view.id, |
| 659 | + &mut HashSet::default(), |
| 660 | + &mut all_views_in_workspace, |
| 661 | + ); |
| 662 | + views.extend(all_views_in_workspace); |
647 | 663 | } |
648 | 664 | views.extend(orphan_views); |
649 | 665 |
|
|
0 commit comments