use std::collections::HashSet;
use crate::control::security::catalog::SystemCatalog;
pub const MAX_DEPTH: usize = 32;
pub fn find_mvs_sourcing(
catalog: &SystemCatalog,
tenant_id: u64,
root_collection: &str,
) -> crate::Result<Vec<String>> {
let all = catalog.load_all_materialized_views()?;
use std::collections::HashMap;
let mut by_source: HashMap<String, Vec<String>> = HashMap::new();
for mv in all.iter().filter(|m| m.tenant_id == tenant_id) {
by_source
.entry(mv.source.clone())
.or_default()
.push(mv.name.clone());
}
let mut found: HashSet<String> = HashSet::new();
let mut frontier: Vec<String> = vec![root_collection.to_string()];
let mut depth = 0usize;
while !frontier.is_empty() {
depth += 1;
if depth > MAX_DEPTH {
return Err(crate::Error::CascadeCycle {
tenant_id,
root: root_collection.to_string(),
depth: MAX_DEPTH,
});
}
let mut next: Vec<String> = Vec::new();
for src in frontier {
if let Some(mvs) = by_source.get(&src) {
for mv_name in mvs {
if found.insert(mv_name.clone()) {
next.push(mv_name.clone());
}
}
}
}
frontier = next;
}
let mut out: Vec<String> = found.into_iter().collect();
out.sort();
Ok(out)
}