uqa-execution 0.4.0

Volcano physical operators with row-batch pipelines
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

//! Read-only access retained by physical table sources.

use parking_lot::RwLockReadGuard;
use uqa_sql::ast::ColumnDef;
use uqa_storage::document_store::DocumentStore;

/// A direct table read retains the same identity-checked access-share lock as a SQL source. The caller supplies its selected catalog and data handle; binding and wait revalidation stay in execution.
pub fn bind_direct_table_read<T>(
    session: &dyn crate::row_locks::binding::RelationLockSession,
    resolve: impl FnMut() -> Result<
        Option<crate::row_locks::binding::RelationBinding<T>>,
        uqa_sql::SQLError,
    >,
) -> Result<Option<crate::row_locks::binding::RelationBinding<T>>, uqa_sql::SQLError> {
    crate::row_locks::binding::bind_relation(
        session,
        crate::row_locks::RelationLockMode::AccessShare,
        false,
        resolve,
        |_| Ok(()),
    )
}

/// Only column definitions and shared document reads are exposed. A scan cannot mutate catalog state, obtain an engine, or acquire a storage write guard.
pub trait TableRead: Send + Sync {
    fn column_definitions(&self) -> Vec<ColumnDef>;
    fn read_documents(&self) -> RwLockReadGuard<'_, Box<dyn DocumentStore>>;
}

/// The chosen transaction snapshot supplies a table generation and the command's row overlay separately.
pub trait QueryTableAccess: Sync {
    fn serializable_read(
        &self,
        name: &str,
    ) -> Result<Option<crate::serializable::SerializableRelationRead>, uqa_sql::SQLError>;

    fn table(&self, name: &str) -> Result<std::sync::Arc<dyn TableRead>, uqa_sql::SQLError>;
    fn command_overlay_changes(
        &self,
        name: &str,
    ) -> Result<Option<super::document_changes::DocumentChanges>, uqa_sql::SQLError>;
    fn table_doc_count(&self, name: &str) -> Result<u64, uqa_sql::SQLError>;
}