1use std::collections::{BTreeMap, BTreeSet};
15use std::sync::Arc;
16
17use parking_lot::Mutex;
18use serde::{Deserialize, Serialize};
19use uqa_analysis::Analyzer;
20use uqa_core::{DocId, FieldName, IndexStats, Payload, PostingEntry, PostingList, Value};
21
22use crate::backend::{PersistentStorageBackend, PersistentStorageIdentity};
23use crate::document_store::{Document, DocumentStore};
24use crate::inverted_index::{AnalyzerPhase, InvertedIndex};
25use crate::vector_index::{
26 validate_vector_values, VectorIndex, VectorIndexOpenMode, VectorIndexSpec,
27};
28use crate::{StorageBackendError, StorageBackendResult};
29
30mod catalog;
31pub use catalog::KeyValueCatalog;
32mod diskann;
33pub use diskann::identifiers as diskann_identifiers;
34pub use diskann::{
35 publication, DiskANNMaintenanceStatus, DiskANNMaintenanceStep, DiskANNStageStatus,
36 KeyValueDiskANNMaintenance, KeyValueDiskANNMappingMaintenance, KeyValueDiskANNPruner,
37 KeyValueDiskANNSource, KeyValueDiskANNStage, KeyValueDiskANNStore,
38};
39mod graph_commit;
40mod table_owners;
41pub use graph_commit::KeyValueGraphRecords;
42mod hnsw_records;
43mod index_view;
44mod ivf_records;
45mod maintenance_records;
46mod notification_records;
47pub use notification_records::KeyValueNotificationRecords;
48pub(crate) mod record_json;
49pub use maintenance_records::KeyValueMaintenanceRecords;
50mod vector_records;
51pub use hnsw_records::KeyValueHNSWRecords;
52pub use ivf_records::KeyValueIVFRecords;
53pub(crate) mod occurrence_records;
54pub use occurrence_records::KeyValueOccurrenceRecords;
55mod view;
56pub use view::{
57 KeyValueMutation, KeyValueRead, KeyValueReadRevision, KeyValueReadScope,
58 KeyValueVersionedMutation,
59};
60
61const TAG_METADATA: u8 = b'm';
62const TAG_TABLE: u8 = b't';
63const TAG_MODEL: u8 = b'M';
64const TAG_SCORING_PARAMS: u8 = b'S';
65const TAG_NAMED_GRAPH: u8 = b'g';
66const TAG_VERTEX: u8 = b'V';
67const TAG_EDGE: u8 = b'E';
68const TAG_GRAPH_MEMBERSHIP: u8 = b'G';
69const TAG_GRAPH_LOOKUP: u8 = b'J';
70const TAG_ANALYZER: u8 = b'a';
71const TAG_ANALYZER_DESCRIPTOR: u8 = b'D';
72const TAG_FIELD_ANALYZER_BINDING: u8 = b'U';
73const TAG_TABLE_FIELD_ANALYZER: u8 = b'A';
74const TAG_FOREIGN_SERVER: u8 = b'F';
75const TAG_FOREIGN_TABLE: u8 = b'T';
76const TAG_CATALOG_INDEX: u8 = b'C';
77const TAG_PATH_INDEX: u8 = b'P';
78const TAG_PATH_INDEX_DATA: u8 = b'Q';
79const TAG_COLUMN_STATS: u8 = b'c';
80const TAG_SCHEMA: u8 = b's';
81const TAG_SEQUENCE: u8 = b'q';
82const TAG_RELATION: u8 = b'R';
83const TAG_VIEW: u8 = b'w';
84const TAG_DOCUMENT: u8 = b'd';
85const TAG_POSTING: u8 = b'p';
86const TAG_OCCURRENCE_INDEX: u8 = b'e';
87const TAG_POSTING_CLUSTER_SCORE: u8 = b'k';
88const TAG_POSTING_CLUSTER_POSITIONS: u8 = b'o';
89const TAG_POSTING_DOCUMENT: u8 = b'x';
90const TAG_DOC_LENGTH: u8 = b'l';
91const TAG_FIELD_STATS: u8 = b'f';
92const TAG_REVERSE_POSTING: u8 = b'r';
93const TAG_VECTOR: u8 = b'v';
94const TAG_BTREE_INDEX: u8 = b'B';
95const TAG_BTREE_ENTRY: u8 = b'b';
96const TAG_NAMED_BTREE_INDEX: u8 = b'N';
97const TAG_NAMED_BTREE_ENTRY: u8 = b'n';
98const TAG_IVF_METADATA: u8 = b'I';
99const TAG_IVF_CENTROID: u8 = b'i';
100const TAG_IVF_ASSIGNMENT: u8 = b'j';
101const TAG_HNSW_METADATA: u8 = b'H';
102const TAG_HNSW_NODE: u8 = b'h';
103
104const DOCUMENT_VALUE_V1_PREFIX: &[u8] = b"\0uqa-document-json-v1\0";
109const DOCUMENT_VALUE_V2_PREFIX: &[u8] = b"\0uqa-document-record-v2\0";
110
111#[derive(Debug, Clone)]
112enum KeyValueBatchOperation {
113 Put(Vec<u8>, Vec<u8>),
114 Delete(Vec<u8>),
115 DeletePrefix(Vec<u8>),
116}
117
118pub trait KeyValueBatch {
120 fn serializable_participant(&self) -> Option<crate::mvcc::SerializableTransactionId> {
122 None
123 }
124 fn observe_serializable_write(
126 &mut self,
127 _predicate: crate::mvcc::SerializablePredicate<'_>,
128 ) -> StorageBackendResult<()> {
129 Err(StorageBackendError::Other(
130 "atomic serializable write observations are not supported".into(),
131 ))
132 }
133 fn put_unused(&mut self, key: &[u8], value: &[u8]) -> StorageBackendResult<()> {
135 self.put(key, value)
136 }
137 fn require_unchanged(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
139 Err(StorageBackendError::Other(
140 "commit-time record requirements are not supported".into(),
141 ))
142 }
143 fn require_observed(
145 &mut self,
146 _key: &[u8],
147 _revision: &KeyValueReadRevision,
148 ) -> StorageBackendResult<()> {
149 Err(StorageBackendError::Other(
150 "observed metadata requirements are not supported".into(),
151 ))
152 }
153 fn put_observed(
155 &mut self,
156 _key: &[u8],
157 _value: &[u8],
158 _revision: &KeyValueReadRevision,
159 ) -> StorageBackendResult<()> {
160 Err(StorageBackendError::Other(
161 "observed metadata replacements are not supported".into(),
162 ))
163 }
164 fn put_with_retained_source(
166 &mut self,
167 _key: &[u8],
168 _value: &[u8],
169 _source: Arc<dyn KeyValueRead + Send + Sync>,
170 ) -> StorageBackendResult<()> {
171 Err(StorageBackendError::Other(
172 "private metadata read sources are not supported".into(),
173 ))
174 }
175 fn touch_marker(&mut self, _key: &[u8], _value: &[u8]) -> StorageBackendResult<()> {
177 Err(StorageBackendError::Other(
178 "mergeable revision markers are not supported".into(),
179 ))
180 }
181
182 fn replace_diskann_origin(&mut self, _key: &[u8], _value: &[u8]) -> StorageBackendResult<()> {
184 Err(StorageBackendError::Other(
185 "DiskANN population mutations are not supported".into(),
186 ))
187 }
188
189 fn invalidate_diskann_origin(&mut self, key: &[u8]) -> StorageBackendResult<()> {
191 self.delete(key)
192 }
193
194 fn publish_diskann_population(
196 &mut self,
197 _key: &[u8],
198 _template: &[u8],
199 _origins: crate::diskann_index::pages::DiskANNOriginReader,
200 ) -> StorageBackendResult<()> {
201 Err(StorageBackendError::Other(
202 "DiskANN population publication is not supported".into(),
203 ))
204 }
205
206 fn retire_diskann_population(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
208 Err(StorageBackendError::Other(
209 "DiskANN population retirement is not supported".into(),
210 ))
211 }
212 fn observe_identifier(&mut self, _namespace: &[u8], _value: u64) -> StorageBackendResult<()> {
214 Err(StorageBackendError::Other(
215 "durable identifier observations are not supported".into(),
216 ))
217 }
218 fn inherit_identifiers(&mut self, _from: &[u8], _to: &[u8]) -> StorageBackendResult<()> {
220 Err(StorageBackendError::Other(
221 "durable identifier inheritance is not supported".into(),
222 ))
223 }
224 fn put(&mut self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
225 fn delete(&mut self, key: &[u8]) -> StorageBackendResult<()>;
226 fn delete_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()>;
227 fn delete_prefix_allow_absent(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
229 self.delete_prefix(prefix)
230 }
231 fn ivf_mutation(
233 &mut self,
234 _metadata: &[u8],
235 _mutation: crate::ivf_index::IVFMutation<'_>,
236 ) -> StorageBackendResult<()> {
237 Ok(())
238 }
239 fn preview_ivf_record(&mut self, key: &[u8], value: Option<&[u8]>) -> StorageBackendResult<()> {
241 match value {
242 Some(value) => self.put(key, value),
243 None => self.delete(key),
244 }
245 }
246 fn preview_ivf_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
247 self.delete_prefix(prefix)
248 }
249 fn fence_ivf_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
251 Ok(())
252 }
253 fn hnsw_mutation(
255 &mut self,
256 _metadata: &[u8],
257 _mutation: crate::hnsw_index::HNSWMutation<'_>,
258 ) -> StorageBackendResult<()> {
259 Ok(())
260 }
261 fn preview_hnsw_record(
263 &mut self,
264 key: &[u8],
265 value: Option<&[u8]>,
266 ) -> StorageBackendResult<()> {
267 match value {
268 Some(value) => self.put(key, value),
269 None => self.delete(key),
270 }
271 }
272 fn preview_hnsw_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
273 self.delete_prefix(prefix)
274 }
275 fn fence_hnsw_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
277 Ok(())
278 }
279 fn replace_occurrence_record(
281 &mut self,
282 key: &[u8],
283 value: Option<&[u8]>,
284 ) -> StorageBackendResult<()> {
285 match value {
286 Some(value) => self.put(key, value),
287 None => self.delete(key),
288 }
289 }
290 fn invalidate_occurrence_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
292 self.delete_prefix(prefix)
293 }
294 fn occurrence_document(&mut self, _table: &str, _document: DocId) -> StorageBackendResult<()> {
296 Ok(())
297 }
298 fn reset_occurrences(&mut self, _table: &str) -> StorageBackendResult<()> {
300 Ok(())
301 }
302 fn fence_record(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
304 Ok(())
305 }
306 fn replace_statistics_maintenance(
308 &mut self,
309 key: &[u8],
310 value: &[u8],
311 ) -> StorageBackendResult<()> {
312 self.put(key, value)
313 }
314 fn graph_mutation(
316 &mut self,
317 _mutation: crate::mvcc::GraphMutation<'_>,
318 ) -> StorageBackendResult<()> {
319 Ok(())
320 }
321 fn preview_graph_invalidation(
323 &mut self,
324 key: &[u8],
325 value: Option<&[u8]>,
326 ) -> StorageBackendResult<()> {
327 match value {
328 Some(value) => self.put(key, value),
329 None => self.delete(key),
330 }
331 }
332 fn replace_graph_cache(
334 &mut self,
335 key: &[u8],
336 value: Option<&[u8]>,
337 ) -> StorageBackendResult<()> {
338 match value {
339 Some(value) => self.put(key, value),
340 None => self.delete(key),
341 }
342 }
343 fn commit(self: Box<Self>) -> StorageBackendResult<()>;
344}
345
346pub use vector_index::guards::KeyValueVectorFieldGuards;
347
348pub(crate) fn diskann_tombstone_prefixes() -> [&'static [u8]; 5] {
349 [
350 diskann::READ_PREFIX,
351 vector_index::origin::ROOT,
352 vector_index::origin::journal::ROOT,
353 vector_index::guards::ROOT,
354 vector_index::origin::populations::ROOT,
355 ]
356}
357
358pub trait KeyValueStore: Send + Sync {
360 fn resource_leases(&self) -> Option<&dyn crate::mvcc::ResourceLeaseProvider> {
362 None
363 }
364
365 fn auxiliary_encryption_key(&self) -> Option<crate::StorageEncryptionKey> {
367 None
368 }
369
370 fn retention_control(&self) -> Option<crate::read_control::StorageReadControl> {
372 None
373 }
374
375 fn notification_publications(
377 &self,
378 ) -> Option<&dyn crate::notifications::NotificationPublicationStore> {
379 None
380 }
381
382 fn serializable_session(&self) -> Option<&dyn crate::mvcc::SerializableSession> {
384 None
385 }
386
387 fn reclaim_obsolete(&self) -> StorageBackendResult<()> {
389 if self.transaction_model().is_versioned() {
390 return Err(StorageBackendError::Other(
391 "versioned KeyValue maintenance is not implemented by this store".into(),
392 ));
393 }
394 Ok(())
395 }
396
397 fn vacuum(&self) -> StorageBackendResult<()> {
399 self.reclaim_obsolete()
400 }
401
402 fn write_cancellation(&self) -> Option<uqa_core::CancellationToken> {
404 None
405 }
406
407 fn open_controlled_session(
409 &self,
410 _control: &crate::read_control::StorageReadControl,
411 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
412 Err(StorageBackendError::Other(
413 "controlled independent sessions are not implemented for this store".into(),
414 ))
415 }
416
417 fn open_session_with_cancellation(
419 &self,
420 cancellation: &uqa_core::CancellationToken,
421 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
422 cancellation.check()?;
423 if self.transaction_model().is_versioned() {
424 return Err(StorageBackendError::Other(
425 "cancellable independent KeyValue sessions are not implemented by this store"
426 .into(),
427 ));
428 }
429 self.open_session()
430 }
431
432 fn open_retained_read_session(
434 &self,
435 cancellation: &uqa_core::CancellationToken,
436 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
437 cancellation.check()?;
438 Err(StorageBackendError::Other(
439 "retained read sessions are not implemented by this KeyValue store".into(),
440 ))
441 }
442
443 fn transaction_model(&self) -> crate::StorageTransactionModel {
445 crate::StorageTransactionModel::ProviderSerialized
446 }
447
448 fn identifier_allocator(&self) -> Option<&dyn crate::mvcc::IdentifierAllocator> {
450 None
451 }
452
453 fn with_read_view(&self, _read: &mut KeyValueReadScope<'_>) -> StorageBackendResult<()> {
455 Err(StorageBackendError::Other(
456 "compound KeyValue reads are not supported by this store".into(),
457 ))
458 }
459
460 fn with_mutation(&self, _mutate: &mut KeyValueMutation<'_>) -> StorageBackendResult<()> {
462 Err(StorageBackendError::Other(
463 "atomic KeyValue evaluation is not supported by this store".into(),
464 ))
465 }
466
467 fn with_versioned_mutation(
469 &self,
470 _mutate: &mut KeyValueVersionedMutation<'_>,
471 ) -> StorageBackendResult<()> {
472 Err(StorageBackendError::Other(
473 "versioned KeyValue mutation origins are not supported by this store".into(),
474 ))
475 }
476
477 fn transaction_affinity(&self) -> Option<crate::StorageSessionAffinity> {
479 None
480 }
481
482 fn storage_identity(&self) -> StorageBackendResult<Option<PersistentStorageIdentity>> {
483 Ok(None)
484 }
485
486 fn open_session(&self) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
488 Err(StorageBackendError::Other(
489 "independent sessions are not implemented for this KeyValue store".into(),
490 ))
491 }
492
493 fn get(&self, key: &[u8]) -> StorageBackendResult<Option<Vec<u8>>>;
494 fn visit_value(
496 &self,
497 _key: &[u8],
498 control: &crate::read_control::StorageReadControl,
499 _visit: &mut crate::read_control::ValueReadVisitor<'_>,
500 ) -> StorageBackendResult<()> {
501 control.check()?;
502 Err(StorageBackendError::Other(
503 "controlled value reads are not supported by this KeyValue store".into(),
504 ))
505 }
506 fn visit_value_bounded(
508 &self,
509 _key: &[u8],
510 _max_bytes: usize,
511 control: &crate::read_control::StorageReadControl,
512 _visit: &mut crate::read_control::ValueReadVisitor<'_>,
513 ) -> StorageBackendResult<()> {
514 control.check()?;
515 Err(StorageBackendError::Other(
516 "size-bounded value reads are not supported by this KeyValue store".into(),
517 ))
518 }
519
520 fn visit_prefix_after(
522 &self,
523 _prefix: &[u8],
524 _after: Option<&[u8]>,
525 _limit: usize,
526 control: &crate::read_control::StorageReadControl,
527 _visit: &mut crate::read_control::KeyValueReadVisitor<'_>,
528 ) -> StorageBackendResult<()> {
529 control.check()?;
530 Err(StorageBackendError::Other(
531 "controlled prefix reads are not supported by this KeyValue store".into(),
532 ))
533 }
534 fn contains_prefix_budgeted(
536 &self,
537 prefix: &[u8],
538 control: &crate::read_control::StorageReadControl,
539 ) -> StorageBackendResult<bool> {
540 let mut found = false;
541 self.visit_prefix_after(prefix, None, 1, control, &mut |_, _| {
542 found = true;
543 Ok(())
544 })?;
545 control.check()?;
546 Ok(found)
547 }
548
549 fn contains_key(&self, key: &[u8]) -> StorageBackendResult<bool> {
550 self.get(key).map(|value| value.is_some())
551 }
552 fn put(&self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
553 fn delete(&self, key: &[u8]) -> StorageBackendResult<()>;
554 fn scan_prefix(&self, prefix: &[u8]) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>>;
555 fn scan_prefix_after(
559 &self,
560 prefix: &[u8],
561 after: Option<&[u8]>,
562 limit: usize,
563 ) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>> {
564 if limit == 0 {
565 return Ok(Vec::new());
566 }
567 Ok(self
568 .scan_prefix(prefix)?
569 .into_iter()
570 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
571 .take(limit)
572 .collect())
573 }
574 fn scan_prefix_keys_after(
579 &self,
580 prefix: &[u8],
581 after: Option<&[u8]>,
582 limit: usize,
583 ) -> StorageBackendResult<Vec<Vec<u8>>> {
584 if limit == 0 {
585 return Ok(Vec::new());
586 }
587 Ok(self
588 .scan_prefix(prefix)?
589 .into_iter()
590 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
591 .take(limit)
592 .map(|(key, _)| key)
593 .collect())
594 }
595 fn first_prefix_after(
596 &self,
597 prefix: &[u8],
598 after: Option<&[u8]>,
599 ) -> StorageBackendResult<Option<(Vec<u8>, Vec<u8>)>> {
600 Ok(self
601 .scan_prefix(prefix)?
602 .into_iter()
603 .find(|(key, _)| after.is_none_or(|after| key.as_slice() > after)))
604 }
605 fn delete_prefix(&self, prefix: &[u8]) -> StorageBackendResult<usize>;
606 fn batch(&self) -> Box<dyn KeyValueBatch + '_>;
607
608 fn begin_transaction(&self) -> StorageBackendResult<()> {
609 Err(StorageBackendError::Other(
610 "KeyValue transaction begin is not implemented for this store".into(),
611 ))
612 }
613
614 fn begin_read_transaction(&self) -> StorageBackendResult<()> {
615 self.begin_transaction()
616 }
617
618 fn begin_upgradeable_transaction(&self) -> StorageBackendResult<()> {
619 self.begin_transaction()
620 }
621
622 fn in_transaction(&self) -> bool;
623
624 fn transaction_has_written(&self) -> StorageBackendResult<bool>;
626
627 fn change_version(&self) -> StorageBackendResult<Option<u64>> {
628 Ok(None)
629 }
630
631 fn read_view_revision(&self) -> StorageBackendResult<Option<KeyValueReadRevision>> {
633 Ok(None)
634 }
635
636 fn change_version_monitor_is_nonblocking(&self) -> StorageBackendResult<bool> {
637 Ok(true)
638 }
639
640 fn pin_transaction_snapshot(&self) -> StorageBackendResult<()> {
641 Ok(())
642 }
643
644 fn refresh_transaction_snapshot(
646 &self,
647 _cancellation: &uqa_core::CancellationToken,
648 ) -> StorageBackendResult<()> {
649 Err(StorageBackendError::Other(
650 "transaction snapshot refresh is not supported by this KeyValue store".into(),
651 ))
652 }
653
654 fn commit_transaction(&self) -> StorageBackendResult<()> {
655 Err(StorageBackendError::Other(
656 "KeyValue transaction commit is not implemented for this store".into(),
657 ))
658 }
659
660 fn rollback_transaction(&self) -> StorageBackendResult<()> {
661 Err(StorageBackendError::Other(
662 "KeyValue transaction rollback is not implemented for this store".into(),
663 ))
664 }
665
666 fn savepoint(&self, _name: &str) -> StorageBackendResult<()> {
667 Err(StorageBackendError::Other(
668 "KeyValue savepoints are not implemented for this store".into(),
669 ))
670 }
671
672 fn release_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
673 Err(StorageBackendError::Other(
674 "KeyValue savepoint release is not implemented for this store".into(),
675 ))
676 }
677
678 fn rollback_to_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
679 Err(StorageBackendError::Other(
680 "KeyValue savepoint rollback is not implemented for this store".into(),
681 ))
682 }
683}
684
685mod btree_index;
686mod codec;
687pub mod conformance;
688mod document_store;
689mod hnsw_index;
690mod hnsw_persistence;
691mod index_keys;
692mod inverted_index;
693mod ivf_index;
694mod ivf_persistence;
695mod memory_store;
696pub mod occurrence_format;
697mod occurrence_keys;
698mod storage_backend;
699mod vector_index;
700
701pub use codec::prefix_upper_bound;
702pub use document_store::KeyValueDocumentStore;
703pub use hnsw_index::KeyValueHNSWIndex;
704pub use inverted_index::{KeyValueInvertedIndex, OccurrenceStorage};
705pub use ivf_index::KeyValueIVFIndex;
706pub use memory_store::MemoryKeyValueStore;
707pub use storage_backend::KeyValueStorageBackend;
708pub use vector_index::{
709 DiskANNCanonicalVectorVisitor, KeyValueDiskANNCanonical, KeyValueDiskANNHandle,
710 KeyValueDiskANNPopulationRecords, KeyValueVectorIndex, RetainedDiskANNCanonical,
711};
712
713#[cfg(test)]
714mod tests;