Skip to main content

uqa_storage/hnsw_index/
canonical.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Canonical reads seek active identities without materializing a document directory.
8
9use super::{types::active_key, HNSWIndex};
10use crate::{
11    read_control::StorageReadControl,
12    vector_index::{copy_vector, VectorRead},
13    StorageBackendResult,
14};
15use uqa_core::{memory::BudgetedVec, DocId};
16
17impl VectorRead for HNSWIndex {
18    fn check_control(&self, control: &StorageReadControl) -> StorageBackendResult<()> {
19        control.check()
20    }
21    fn dimensions(&self) -> u32 {
22        self.dimensions
23    }
24
25    fn next_document_after(
26        &self,
27        after: Option<DocId>,
28        control: &StorageReadControl,
29    ) -> StorageBackendResult<Option<DocId>> {
30        control.check()?;
31        Ok(self
32            .active
33            .next(after.map(|doc| active_key(doc, u32::MAX)))?
34            .map(|(key, _)| (key >> 32) as u64))
35    }
36
37    fn document_vector_count(
38        &self,
39        document: DocId,
40        control: &StorageReadControl,
41    ) -> StorageBackendResult<u64> {
42        let mut after = active_key(document, 0).checked_sub(1);
43        let mut count = 0;
44        while let Some((key, _)) = self.active.next(after)? {
45            control.check()?;
46            if key >> 32 != u128::from(document) {
47                break;
48            }
49            if u64::from(key as u32) != count {
50                return Err(crate::mvcc::VersionError::InvalidEncoding(
51                    "HNSW live document vector ordinals are not contiguous",
52                )
53                .into_storage_error());
54            }
55            count += 1;
56            after = Some(key);
57        }
58        Ok(count)
59    }
60
61    fn read_vector(
62        &self,
63        document: DocId,
64        ordinal: u32,
65        control: &StorageReadControl,
66    ) -> StorageBackendResult<Option<BudgetedVec<f32>>> {
67        control.check()?;
68        let Some(node_id) = self.active.get(active_key(document, ordinal))? else {
69            return Ok(None);
70        };
71        let node = self
72            .node(*node_id)?
73            .filter(|node| {
74                !node.deleted && node.doc_id == document && node.vector_ordinal == ordinal
75            })
76            .ok_or_else(|| {
77                crate::mvcc::VersionError::InvalidEncoding(
78                    "HNSW canonical identity has no active raw vector",
79                )
80                .into_storage_error()
81            })?;
82        copy_vector(&self.raw_vector(node.id)?.values, control).map(Some)
83    }
84}