uqa-engine 0.5.1

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 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,
            memory: self.session.as_ref(),
        }
    }
}
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 live_table_doc_id_page(
        &self,
        table: &str,
        after: Option<DocId>,
        limit: usize,
        control: &uqa_storage::read_control::StorageReadControl,
    ) -> Result<uqa_core::memory::BudgetedVec<DocId>, SQLError> {
        let state = self.require_table(table)?;
        let changes = self.command_overlay_changes(table)?.unwrap_or_default();
        let source = state.document_store.read();
        uqa_execution::query::document_changes::VisibleDocumentIds {
            source: source.as_ref(),
            changes: &changes,
            control,
        }
        .page(after, limit, control, true)
        .map_err(|error| {
            uqa_sql::catalog::errors::storage_error("column rewrite identity page", &error)
        })
    }
    fn get_document(&self, table: &str, doc_id: DocId) -> Result<Option<Document>, SQLError> {
        Engine::get_live_document(self, table, doc_id)
    }
    fn raw_document(&self, table: &str, doc_id: DocId) -> Result<Option<Document>, SQLError> {
        Engine::get_raw_live_document(self, table, doc_id)
    }
    fn command_overlay_changes(
        &self,
        table: &str,
    ) -> Result<Option<uqa_execution::query::document_changes::DocumentChanges>, SQLError> {
        Engine::command_overlay_changes(self, table)
    }
}
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 staged_matches(
        &self,
        table: &str,
        columns: &[String],
        values: &[Value],
    ) -> Result<Vec<DocId>, SQLError> {
        Engine::command_overlay_matches(self, table, columns, values)
    }
    fn staged_expression_matches(
        &self,
        table: &str,
        physical_key: &str,
        values: &[Value],
    ) -> Result<uqa_execution::mutation::overlay::CommandIndexProbe, SQLError> {
        let table = self.command_overlay_table_name(table)?;
        let control = self.query_retention_control()?;
        uqa_execution::mutation::overlay::CommandMutationOverlay::expression_matches(
            &mut self.session.command_mutation_overlays.lock(),
            &table,
            physical_key,
            values,
            &control,
        )
    }
    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 referenced_key_is_deferred(
        &self,
        table: &str,
        key: &ForeignKey,
        derived: Option<&uqa_sql::ast::ReferencedPartitionConstraint>,
    ) -> Result<bool, SQLError> {
        Engine::referenced_key_is_deferred(self, table, key, derived)
    }
    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,
        )
    }
}