uqa-engine 0.4.0

Engine: schema-aware table store, catalog restore, transactions
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! Bind constraint execution to the active catalog, row generation, and transaction.
use crate::Engine;
use std::collections::BTreeSet;
use uqa_core::{DocId, PostingList, Predicate, Value};
use uqa_execution::catalog::security::schema::SchemaAclPrivilege;
use uqa_execution::{
    mutation::constraints::context::{
        ConstraintCatalog, ConstraintContext, ConstraintDiagnosticContext,
        ConstraintDiagnosticSource, ConstraintTransactions, MutationIndexRead, MutationNamespace,
        MutationRead,
    },
    row_locks::LockAcquire,
};
use uqa_sql::catalog::roles::RoleReference;
use uqa_sql::{
    ast::{ColumnDef, ColumnType, ForeignKey, TableCheck},
    catalog::index::EnforcedKey,
    SQLError,
};
use uqa_storage::{document_store::Document, ValueIndexKey};
impl Engine {
    pub(crate) fn constraint_execution_context(&self) -> ConstraintContext<'_> {
        ConstraintContext {
            catalog: self,
            reads: self,
            indexes: self,
            transactions: self,
            locks: self,
            namespace: self,
            referrers: self,
            partitions: self.partition_context(),
            diagnostics: self,
        }
    }
}
impl ConstraintDiagnosticSource for Engine {
    fn diagnostic_context(&self) -> ConstraintDiagnosticContext<'_> {
        ConstraintDiagnosticContext {
            catalog: self.catalog_execution(),
            authorization: self.table_authorization_context(),
        }
    }
}
impl ConstraintCatalog for Engine {
    fn try_unique_columns(&self, table: &str) -> Result<Vec<String>, String> {
        Engine::unique_columns_in_execution(self, table).map_err(|error| error.to_string())
    }
    fn try_check_constraint_definitions(&self, table: &str) -> Result<Vec<TableCheck>, String> {
        Engine::check_constraint_definitions_in_execution(self, table)
            .map_err(|error| error.to_string())
    }
    fn try_foreign_keys(&self, table: &str) -> Result<Vec<ForeignKey>, String> {
        Engine::foreign_keys_in_execution(self, table).map_err(|error| error.to_string())
    }
    fn column_type(&self, table: &str, column: &str) -> Result<Option<ColumnType>, String> {
        Engine::column_type(self, table, column).map_err(|error| error.to_string())
    }
    fn hierarchy_scan_tables(
        &self,
        table: &str,
        descendants: bool,
    ) -> Result<Vec<String>, SQLError> {
        Engine::hierarchy_scan_tables(self, table, descendants)
    }
}
impl MutationRead for Engine {
    fn table_doc_ids(&self, table: &str) -> Result<Vec<DocId>, SQLError> {
        Engine::query_table_doc_ids(self, table)
    }
    fn live_table_doc_ids(&self, table: &str) -> Result<Vec<DocId>, SQLError> {
        Engine::live_table_doc_ids(self, table)
    }
    fn get_document(&self, table: &str, doc_id: DocId) -> Result<Option<Document>, SQLError> {
        Engine::get_live_document(self, table, doc_id)
    }
    fn command_overlay_changed_ids(
        &self,
        table: &str,
    ) -> Result<Option<BTreeSet<DocId>>, SQLError> {
        self.command_overlay_changes(table)
            .map(|changes| changes.map(|changes| changes.changes().map(|(id, _)| id).collect()))
    }
}
impl MutationIndexRead for Engine {
    fn index_definitions(
        &self,
    ) -> Result<
        std::sync::Arc<uqa_execution::catalog::index::physical::PhysicalIndexDefinitions>,
        SQLError,
    > {
        self.physical_index_definitions()
            .map_err(|error| uqa_sql::catalog::errors::storage_error("index definitions", &error))
    }
    fn find_conflict(
        &self,
        table: &str,
        columns: &[String],
        values: &[Value],
    ) -> Result<Option<DocId>, SQLError> {
        Engine::find_mutation_conflict(self, table, columns, values)
    }
    fn value_index_scan_key(
        &self,
        table: &str,
        key: &ValueIndexKey,
        predicate: &Predicate,
    ) -> Result<Option<PostingList>, SQLError> {
        Engine::value_index_scan_key(self, table, key, predicate)
    }
}
impl ConstraintTransactions for Engine {
    fn foreign_key_is_deferred(&self, table: &str, key: &ForeignKey) -> Result<bool, SQLError> {
        Engine::foreign_key_is_deferred(self, table, key)
    }
    fn refresh_explicit_statement_snapshot(&self) -> Result<(), SQLError> {
        Engine::refresh_explicit_statement_snapshot(self)
    }
    fn lock_key_reservation(&self, key: [u8; 32], table: &str) -> Result<LockAcquire, SQLError> {
        Engine::lock_key_reservation(self, key, table)
    }
}
impl MutationNamespace for Engine {
    fn current_role(&self) -> RoleReference {
        Engine::current_role(self)
    }
    fn require_schema_privilege(
        &self,
        schema: &str,
        role: &RoleReference,
        privilege: SchemaAclPrivilege,
    ) -> Result<(), SQLError> {
        Engine::require_schema_privilege(self, schema, role, privilege)
    }
}

impl uqa_sql::semantics::conflict::ConflictCatalog for Engine {
    fn try_describe_table(&self, table: &str) -> Result<Option<Vec<ColumnDef>>, String> {
        Engine::describe_table_in_execution(self, table).map_err(|error| error.to_string())
    }
    fn enforced_keys(&self, table: &str) -> Result<Vec<EnforcedKey>, String> {
        Engine::enforced_keys(self, table).map_err(|error| error.to_string())
    }
    fn try_declared_table_constraints(
        &self,
        table: &str,
    ) -> Result<uqa_sql::ast::TableConstraintSet, String> {
        Engine::try_declared_table_constraints(self, table).map_err(|error| error.to_string())
    }
}
impl uqa_sql::semantics::conflict::InferenceBindingScope for Engine {
    fn binding_scope(&self) -> Result<uqa_sql::binding::snapshot::BindingSnapshot, SQLError> {
        let scope = super::query_scope::new_for_catalog_binding(self);
        uqa_execution::query::binding::binding_context(&scope)
            .map(uqa_sql::binding::snapshot::BindingSnapshot::from)
    }
}
impl Engine {
    pub(crate) fn inference_context(&self) -> uqa_sql::semantics::conflict::InferenceContext<'_> {
        uqa_sql::semantics::conflict::InferenceContext {
            catalog: self,
            aggregates: self,
            routines: self,
            binding: self,
        }
    }
}

impl Engine {
    pub(crate) fn validate_deferred_foreign_key_checks(
        &self,
        checks: &[crate::DeferredForeignKeyCheck],
        targets: Option<&std::collections::BTreeSet<crate::ConstraintIdentity>>,
    ) -> Result<(), SQLError> {
        uqa_execution::mutation::constraints::validate_deferred_foreign_key_checks(
            self.constraint_execution_context(),
            checks,
            targets,
        )
    }
}