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 let mut oids = BTreeSet::new();
25 for (relation, view) in views {
26 if !object_ids.insert(view.object_id) {
27 return Err(format!(
28 "view `{}` has a duplicate object identity",
29 relation.qualified_name()
30 ));
31 }
32 if let Some(recorded) = view.catalog_oids {
33 if !recorded.is_valid_for(crate::catalog::relation_oids::RelationOidKind::View)
34 || !recorded.claimed().all(|oid| oids.insert(oid))
35 {
36 return Err(format!(
37 "view `{}` records invalid catalog OIDs",
38 relation.qualified_name()
39 ));
40 }
41 }
42 }
43 Ok(())
44}
45
46pub fn validate_restored_view_security(
47 roles: &dyn RoleCatalogGuards,
48 view_name: &str,
49 view: &StoredView,
50) -> Result<(), String> {
51 view.security
52 .validate(view.output_columns.as_deref(), &roles.role_definitions())
53 .map_err(|error| format!("view `{view_name}` has invalid privilege metadata: {error}"))?;
54 Ok(())
55}
56pub fn validate_migrated_view_security(
57 roles: &dyn RoleCatalogGuards,
58 views: &BTreeMap<RelationIdentity, StoredView>,
59) -> Result<(), String> {
60 for (relation, view) in views {
61 let output_columns = view.output_columns.as_deref().ok_or_else(|| {
62 format!(
63 "view `{}` has no public column metadata after catalog migration",
64 relation.qualified_name()
65 )
66 })?;
67 view.security
68 .validate(Some(output_columns), &roles.role_definitions())
69 .map_err(|error| {
70 format!(
71 "view `{}` has invalid privilege metadata after migration: {error}",
72 relation.qualified_name()
73 )
74 })?;
75 }
76 Ok(())
77}
78pub fn restored_view_output_columns(schema: &RowSchema) -> Vec<String> {
79 schema
80 .columns()
81 .iter()
82 .enumerate()
83 .map(|(position, column)| schema.public_name(position).unwrap_or(column).to_string())
84 .collect()
85}
86
87#[cfg(test)]
88mod tests;