Skip to main content

uqa_storage/mvcc/view/
selected.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Lazy requested-key reads retain private cursors but no physical committed read window.
8
9use super::{
10    BorrowedRecord, MergedRecordSnapshot, RecordKeyIterator, RecordMetadata, RecordPointVisitor,
11    RecordValueVisitor,
12};
13use crate::mvcc::overlay::PrivateRecordSelection;
14use crate::mvcc::VersionResult;
15use crate::read_control::StorageReadControl;
16
17/// Selected reads on one immutable command view. Ascending keys reuse private spill readers and seek across gaps; backwards keys restart at their own bound. Duplicates, tombstones and missing keys preserve point-read semantics.
18pub struct SelectedRecordRead<'a> {
19    view: &'a MergedRecordSnapshot,
20    private: PrivateRecordSelection<'a>,
21}
22
23impl MergedRecordSnapshot {
24    /// Prepare lazy selected reads without opening a provider window or reading a key. Each call closes its own physical read window before returning.
25    pub fn selected(&self, control: &StorageReadControl) -> SelectedRecordRead<'_> {
26        SelectedRecordRead {
27            view: self,
28            private: PrivateRecordSelection::new(&self.private, control),
29        }
30    }
31}
32
33impl SelectedRecordRead<'_> {
34    /// Borrow requested keys lazily, stopping before producing another key on a false visitor or error. Key production and visitors are internal and must not reenter persistence. Reusing this reader after a stopped batch preserves its private cursor; a view without private changes keeps the provider's single read window.
35    pub fn visit_values(
36        &mut self,
37        keys: &mut RecordKeyIterator<'_>,
38        control: &StorageReadControl,
39        visit: &mut RecordPointVisitor<'_>,
40    ) -> VersionResult<()> {
41        if self.view.private_revision().is_none() {
42            return self.view.committed.visit_values(keys, control, visit);
43        }
44        loop {
45            control.check()?;
46            let Some(key) = keys.next() else {
47                return Ok(());
48            };
49            let key = key?;
50            let mut more = true;
51            self.visit_value(&key, control, &mut |record| {
52                more = visit(&key, record)?;
53                Ok(())
54            })?;
55            control.check()?;
56            if !more {
57                return Ok(());
58            }
59        }
60    }
61
62    /// Read only metadata from private entries; providers with key-only access also avoid committed payloads.
63    pub fn metadata(
64        &mut self,
65        key: &[u8],
66        control: &StorageReadControl,
67    ) -> VersionResult<Option<RecordMetadata>> {
68        if let Some(record) = self.private.metadata(key, control)? {
69            return Ok(Some(record));
70        }
71        self.view.committed.metadata(key, control)
72    }
73
74    /// Borrow one value for an internal storage visitor. The visitor must not reenter persistence; after this call returns no physical read guard remains.
75    pub fn visit_value(
76        &mut self,
77        key: &[u8],
78        control: &StorageReadControl,
79        visit: &mut RecordValueVisitor<'_>,
80    ) -> VersionResult<()> {
81        if let Some(write) = self.private.read(key, control)? {
82            visit(Some(BorrowedRecord {
83                revision: write.expected(),
84                value: write.value(),
85            }))?;
86            control.check()?;
87            return Ok(());
88        }
89        self.view.committed.visit_value(key, control, visit)
90    }
91}