uqa_sql/catalog/stored_view/
restoration.rs1use super::StoredView;
9use crate::{catalog::roles::guards::RoleCatalogGuards, plan::QueryPlan, RowSchema};
10use std::collections::{BTreeMap, BTreeSet};
11use uqa_core::RelationIdentity;
12
13#[derive(serde::Deserialize)]
14#[serde(untagged)]
15pub enum RestoredView {
16 Current(super::StoredViewDefinition),
17 Legacy(QueryPlan),
18}
19
20pub fn validate_restored_view_object_ids(
21 views: &BTreeMap<RelationIdentity, StoredView>,
22) -> Result<(), String> {
23 let mut object_ids = BTreeSet::new();
24 for (relation, view) in views {
25 if !object_ids.insert(view.object_id) {
26 return Err(format!(
27 "view `{}` has a duplicate object identity",
28 relation.qualified_name()
29 ));
30 }
31 }
32 Ok(())
33}
34
35pub fn validate_restored_view_security(
36 roles: &dyn RoleCatalogGuards,
37 view_name: &str,
38 view: &StoredView,
39) -> Result<(), String> {
40 view.security
41 .validate(view.output_columns.as_deref(), &roles.role_definitions())
42 .map_err(|error| format!("view `{view_name}` has invalid privilege metadata: {error}"))?;
43 Ok(())
44}
45pub fn validate_migrated_view_security(
46 roles: &dyn RoleCatalogGuards,
47 views: &BTreeMap<RelationIdentity, StoredView>,
48) -> Result<(), String> {
49 for (relation, view) in views {
50 let output_columns = view.output_columns.as_deref().ok_or_else(|| {
51 format!(
52 "view `{}` has no public column metadata after catalog migration",
53 relation.qualified_name()
54 )
55 })?;
56 view.security
57 .validate(Some(output_columns), &roles.role_definitions())
58 .map_err(|error| {
59 format!(
60 "view `{}` has invalid privilege metadata after migration: {error}",
61 relation.qualified_name()
62 )
63 })?;
64 }
65 Ok(())
66}
67pub fn restored_view_output_columns(schema: &RowSchema) -> Vec<String> {
68 schema
69 .columns()
70 .iter()
71 .enumerate()
72 .map(|(position, column)| schema.public_name(position).unwrap_or(column).to_string())
73 .collect()
74}
75
76#[cfg(test)]
77mod tests;