uqa-storage 0.5.3

Document store, inverted index, IVF/HNSW vectors, B-tree, R*Tree, catalog
Documentation
//
// Unified Query Algebra
//
// Copyright (c) 2023-2026 Cognica, Inc.
//

use std::collections::BTreeMap;
use std::sync::Arc;

use uqa_core::{memory::BudgetedVec, DocId, PathSegment, Value};

use crate::document_store::{Document, DocumentMetadata, SharedDocumentRow, StoredDocument};
use crate::read_control::StorageReadControl;
use crate::{DocumentStore, StorageBackendResult};

use super::{read_only_error, ReadOnlySnapshot};

impl DocumentStore for ReadOnlySnapshot<dyn DocumentStore> {
    fn put_stored(
        &mut self,
        _doc_id: DocId,
        _document: StoredDocument,
    ) -> StorageBackendResult<()> {
        Err(read_only_error())
    }

    fn get_stored(&self, doc_id: DocId) -> StorageBackendResult<Option<StoredDocument>> {
        self.0.get_stored(doc_id)
    }

    fn get_stored_many_controlled(
        &self,
        ids: &[DocId],
        control: &StorageReadControl,
    ) -> StorageBackendResult<crate::RetainedDocumentPage> {
        self.0.get_stored_many_controlled(ids, control)
    }

    fn with_field_ref_controlled(
        &self,
        id: DocId,
        field: &str,
        control: &StorageReadControl,
        visitor: &mut dyn FnMut(Option<&Value>) -> StorageBackendResult<()>,
    ) -> StorageBackendResult<()> {
        if let Some(captured) = &self.2 {
            captured.check()?;
        }
        self.0
            .with_field_ref_controlled(id, field, control, visitor)?;
        if let Some(captured) = &self.2 {
            captured.check()?;
        }
        control.check()
    }

    fn field_presence_controlled(
        &self,
        ids: &[DocId],
        fields: &[&str],
        control: &StorageReadControl,
    ) -> StorageBackendResult<BudgetedVec<bool>> {
        if let Some(captured) = &self.2 {
            captured.check()?;
        }
        let present =
            crate::document_store::read_field_presence(self.0.as_ref(), ids, fields, control)?;
        if let Some(captured) = &self.2 {
            captured.check()?;
        }
        Ok(present)
    }

    fn put(&mut self, _doc_id: DocId, _document: Document) -> StorageBackendResult<()> {
        Err(read_only_error())
    }

    fn get(&self, doc_id: DocId) -> StorageBackendResult<Option<Document>> {
        self.0.get(doc_id)
    }

    fn get_stored_many(
        &self,
        doc_ids: &[DocId],
    ) -> StorageBackendResult<BTreeMap<DocId, StoredDocument>> {
        self.0.get_stored_many(doc_ids)
    }

    fn get_metadata(&self, doc_id: DocId) -> StorageBackendResult<Option<DocumentMetadata>> {
        self.0.get_metadata(doc_id)
    }

    fn contains_doc_id(&self, doc_id: DocId) -> StorageBackendResult<bool> {
        self.0.contains_doc_id(doc_id)
    }

    fn delete(&mut self, _doc_id: DocId) -> StorageBackendResult<()> {
        Err(read_only_error())
    }

    fn clear(&mut self) -> StorageBackendResult<()> {
        Err(read_only_error())
    }

    fn get_field(&self, doc_id: DocId, field: &str) -> StorageBackendResult<Option<Value>> {
        self.0.get_field(doc_id, field)
    }

    fn find_doc_id_by_field(
        &self,
        field: &str,
        value: &Value,
    ) -> StorageBackendResult<Option<DocId>> {
        self.0.find_doc_id_by_field(field, value)
    }

    fn patch_fields(
        &mut self,
        _doc_id: DocId,
        _updates: &BTreeMap<String, Value>,
    ) -> StorageBackendResult<bool> {
        Err(read_only_error())
    }

    fn get_many(&self, doc_ids: &[DocId]) -> StorageBackendResult<BTreeMap<DocId, Document>> {
        self.0.get_many(doc_ids)
    }

    fn get_fields_multi(
        &self,
        doc_ids: &[DocId],
        fields: &[&str],
    ) -> StorageBackendResult<BTreeMap<DocId, Vec<Value>>> {
        self.0.get_fields_multi(doc_ids, fields)
    }

    fn for_each_fields_multi(
        &self,
        doc_ids: &[DocId],
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, Vec<Value>) -> bool,
    ) -> StorageBackendResult<()> {
        self.0.for_each_fields_multi(doc_ids, fields, visitor)
    }

    fn for_each_fields_multi_ref(
        &self,
        doc_ids: &[DocId],
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, &[&Value]) -> bool,
    ) -> StorageBackendResult<()> {
        self.0.for_each_fields_multi_ref(doc_ids, fields, visitor)
    }

    fn for_each_fields_multi_ref_with_presence(
        &self,
        doc_ids: &[DocId],
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, bool, &[&Value]) -> bool,
    ) -> StorageBackendResult<()> {
        self.0
            .for_each_fields_multi_ref_with_presence(doc_ids, fields, visitor)
    }

    fn get_shared_fields(
        &self,
        doc_ids: &[DocId],
        fields: &[&str],
    ) -> StorageBackendResult<Option<Vec<Option<SharedDocumentRow>>>> {
        self.0.get_shared_fields(doc_ids, fields)
    }

    fn get_fields_bulk(
        &self,
        doc_ids: &[DocId],
        field: &str,
    ) -> StorageBackendResult<BTreeMap<DocId, Value>> {
        self.0.get_fields_bulk(doc_ids, field)
    }

    fn has_value(&self, field: &str, value: &Value) -> StorageBackendResult<bool> {
        self.0.has_value(field, value)
    }

    fn find_doc_id_by_fields(
        &self,
        fields: &[String],
        values: &[Value],
    ) -> StorageBackendResult<Option<DocId>> {
        self.0.find_doc_id_by_fields(fields, values)
    }

    fn eval_path(
        &self,
        doc_id: DocId,
        path: &[PathSegment],
    ) -> StorageBackendResult<Option<Value>> {
        self.0.eval_path(doc_id, path)
    }

    fn doc_ids(&self) -> StorageBackendResult<Vec<DocId>> {
        self.0.doc_ids()
    }

    fn next_doc_id(&self, after: Option<DocId>) -> StorageBackendResult<Option<DocId>> {
        self.0.next_doc_id(after)
    }

    fn next_doc_ids(&self, after: Option<DocId>, limit: usize) -> StorageBackendResult<Vec<DocId>> {
        self.0.next_doc_ids(after, limit)
    }

    fn next_doc_ids_controlled(
        &self,
        after: Option<DocId>,
        limit: usize,
        control: &StorageReadControl,
    ) -> StorageBackendResult<BudgetedVec<DocId>> {
        self.0.next_doc_ids_controlled(after, limit, control)
    }

    fn next_shared_fields(
        &self,
        after: Option<DocId>,
        limit: usize,
        fields: &[&str],
    ) -> StorageBackendResult<Option<Vec<(DocId, SharedDocumentRow)>>> {
        self.0.next_shared_fields(after, limit, fields)
    }

    fn for_each_next_fields(
        &self,
        after: Option<DocId>,
        limit: usize,
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, &[&Value]) -> bool,
    ) -> StorageBackendResult<Option<usize>> {
        self.0.for_each_next_fields(after, limit, fields, visitor)
    }

    fn max_doc_id(&self) -> StorageBackendResult<DocId> {
        self.0.max_doc_id()
    }

    fn for_each_next_fields_borrowed(
        &self,
        after: Option<DocId>,
        limit: usize,
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, &[&Value]) -> bool,
    ) -> StorageBackendResult<Option<usize>> {
        if let Some(control) = &self.2 {
            control.check()?;
        }
        let result = self
            .0
            .for_each_next_fields_borrowed(after, limit, fields, visitor)?;
        if let Some(control) = &self.2 {
            control.check()?;
        }
        Ok(result)
    }

    fn for_each_fields_multi_borrowed(
        &self,
        ids: &[DocId],
        fields: &[&str],
        visitor: &mut dyn FnMut(DocId, bool, &[&Value]) -> bool,
    ) -> StorageBackendResult<Option<usize>> {
        if let Some(control) = &self.2 {
            control.check()?;
        }
        let result = self
            .0
            .for_each_fields_multi_borrowed(ids, fields, visitor)?;
        if let Some(control) = &self.2 {
            control.check()?;
        }
        Ok(result)
    }

    fn len(&self) -> StorageBackendResult<usize> {
        self.0.len()
    }

    fn is_empty(&self) -> StorageBackendResult<bool> {
        self.0.is_empty()
    }

    fn iter_all(&self) -> StorageBackendResult<Box<dyn Iterator<Item = (DocId, Document)> + '_>> {
        self.0.iter_all()
    }

    fn snapshot(&self) -> StorageBackendResult<Arc<dyn DocumentStore>> {
        Ok(Arc::new(self.clone()))
    }

    fn retained_snapshot(&self) -> StorageBackendResult<Option<Arc<dyn DocumentStore>>> {
        if let Some(control) = &self.2 {
            control.check()?;
        }
        Ok(self.0.retained_snapshot()?.map(|snapshot| {
            Arc::new(Self(
                snapshot,
                self.1.as_ref().map(Arc::clone),
                self.2.clone(),
                None,
            )) as Arc<dyn DocumentStore>
        }))
    }
}