Skip to main content

uqa_sql/catalog/stored_view/
restoration.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Decode and validate durable view definitions and migrated public metadata.
8use 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;