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 KeyPresenceVisitor, KeyValueMutation, KeyValuePointVisitor, KeyValueRead,
58 KeyValueReadKeyIterator, KeyValueReadRevision, KeyValueReadScope, 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_SEQUENCE_VALUE: u8 = b'L';
84const TAG_RELATION: u8 = b'R';
85const TAG_VIEW: u8 = b'w';
86const TAG_DOCUMENT: u8 = b'd';
87const TAG_POSTING: u8 = b'p';
88const TAG_OCCURRENCE_INDEX: u8 = b'e';
89const TAG_POSTING_CLUSTER_SCORE: u8 = b'k';
90const TAG_POSTING_CLUSTER_POSITIONS: u8 = b'o';
91const TAG_POSTING_DOCUMENT: u8 = b'x';
92const TAG_DOC_LENGTH: u8 = b'l';
93const TAG_FIELD_STATS: u8 = b'f';
94const TAG_REVERSE_POSTING: u8 = b'r';
95const TAG_VECTOR: u8 = b'v';
96const TAG_BTREE_INDEX: u8 = b'B';
97const TAG_BTREE_ENTRY: u8 = b'b';
98const TAG_NAMED_BTREE_INDEX: u8 = b'N';
99const TAG_NAMED_BTREE_ENTRY: u8 = b'n';
100const TAG_IVF_METADATA: u8 = b'I';
101const TAG_IVF_CENTROID: u8 = b'i';
102const TAG_IVF_ASSIGNMENT: u8 = b'j';
103const TAG_HNSW_METADATA: u8 = b'H';
104const TAG_HNSW_NODE: u8 = b'h';
105
106const DOCUMENT_VALUE_V1_PREFIX: &[u8] = b"\0uqa-document-json-v1\0";
111const DOCUMENT_VALUE_V2_PREFIX: &[u8] = b"\0uqa-document-record-v2\0";
112
113#[derive(Debug, Clone)]
114enum KeyValueBatchOperation {
115 Put(Vec<u8>, Vec<u8>),
116 Delete(Vec<u8>),
117 DeletePrefix(Vec<u8>),
118}
119
120pub trait KeyValueBatch {
122 fn serializable_participant(&self) -> Option<crate::mvcc::SerializableTransactionId> {
124 None
125 }
126 fn observe_serializable_write(
128 &mut self,
129 _predicate: crate::mvcc::SerializablePredicate<'_>,
130 ) -> StorageBackendResult<()> {
131 Err(StorageBackendError::Other(
132 "atomic serializable write observations are not supported".into(),
133 ))
134 }
135 fn put_unused(&mut self, key: &[u8], value: &[u8]) -> StorageBackendResult<()> {
137 self.put(key, value)
138 }
139 fn require_unchanged(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
141 Err(StorageBackendError::Other(
142 "commit-time record requirements are not supported".into(),
143 ))
144 }
145 fn require_observed(
147 &mut self,
148 _key: &[u8],
149 _revision: &KeyValueReadRevision,
150 ) -> StorageBackendResult<()> {
151 Err(StorageBackendError::Other(
152 "observed metadata requirements are not supported".into(),
153 ))
154 }
155 fn put_observed(
157 &mut self,
158 _key: &[u8],
159 _value: &[u8],
160 _revision: &KeyValueReadRevision,
161 ) -> StorageBackendResult<()> {
162 Err(StorageBackendError::Other(
163 "observed metadata replacements are not supported".into(),
164 ))
165 }
166 fn put_with_retained_source(
168 &mut self,
169 _key: &[u8],
170 _value: &[u8],
171 _source: Arc<dyn KeyValueRead + Send + Sync>,
172 ) -> StorageBackendResult<()> {
173 Err(StorageBackendError::Other(
174 "private metadata read sources are not supported".into(),
175 ))
176 }
177 fn touch_marker(&mut self, _key: &[u8], _value: &[u8]) -> StorageBackendResult<()> {
179 Err(StorageBackendError::Other(
180 "mergeable revision markers are not supported".into(),
181 ))
182 }
183
184 fn replace_diskann_origin(&mut self, _key: &[u8], _value: &[u8]) -> StorageBackendResult<()> {
186 Err(StorageBackendError::Other(
187 "DiskANN population mutations are not supported".into(),
188 ))
189 }
190
191 fn invalidate_diskann_origin(&mut self, key: &[u8]) -> StorageBackendResult<()> {
193 self.delete(key)
194 }
195
196 fn publish_diskann_population(
198 &mut self,
199 _key: &[u8],
200 _template: &[u8],
201 _origins: crate::diskann_index::pages::DiskANNOriginReader,
202 ) -> StorageBackendResult<()> {
203 Err(StorageBackendError::Other(
204 "DiskANN population publication is not supported".into(),
205 ))
206 }
207
208 fn retire_diskann_population(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
210 Err(StorageBackendError::Other(
211 "DiskANN population retirement is not supported".into(),
212 ))
213 }
214 fn observe_identifier(&mut self, _namespace: &[u8], _value: u64) -> StorageBackendResult<()> {
216 Err(StorageBackendError::Other(
217 "durable identifier observations are not supported".into(),
218 ))
219 }
220 fn inherit_identifiers(&mut self, _from: &[u8], _to: &[u8]) -> StorageBackendResult<()> {
222 Err(StorageBackendError::Other(
223 "durable identifier inheritance is not supported".into(),
224 ))
225 }
226 fn put(&mut self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
227 fn delete(&mut self, key: &[u8]) -> StorageBackendResult<()>;
228 fn delete_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()>;
229 fn delete_prefix_allow_absent(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
231 self.delete_prefix(prefix)
232 }
233 fn ivf_mutation(
235 &mut self,
236 _metadata: &[u8],
237 _mutation: crate::ivf_index::IVFMutation<'_>,
238 ) -> StorageBackendResult<()> {
239 Ok(())
240 }
241 fn preview_ivf_record(&mut self, key: &[u8], value: Option<&[u8]>) -> StorageBackendResult<()> {
243 match value {
244 Some(value) => self.put(key, value),
245 None => self.delete(key),
246 }
247 }
248 fn preview_ivf_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
249 self.delete_prefix(prefix)
250 }
251 fn fence_ivf_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
253 Ok(())
254 }
255 fn hnsw_mutation(
257 &mut self,
258 _metadata: &[u8],
259 _mutation: crate::hnsw_index::HNSWMutation<'_>,
260 ) -> StorageBackendResult<()> {
261 Ok(())
262 }
263 fn preview_hnsw_record(
265 &mut self,
266 key: &[u8],
267 value: Option<&[u8]>,
268 ) -> StorageBackendResult<()> {
269 match value {
270 Some(value) => self.put(key, value),
271 None => self.delete(key),
272 }
273 }
274 fn preview_hnsw_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
275 self.delete_prefix(prefix)
276 }
277 fn fence_hnsw_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
279 Ok(())
280 }
281 fn replace_occurrence_record(
283 &mut self,
284 key: &[u8],
285 value: Option<&[u8]>,
286 ) -> StorageBackendResult<()> {
287 match value {
288 Some(value) => self.put(key, value),
289 None => self.delete(key),
290 }
291 }
292 fn invalidate_occurrence_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
294 self.delete_prefix(prefix)
295 }
296 fn occurrence_document(&mut self, _table: &str, _document: DocId) -> StorageBackendResult<()> {
298 Ok(())
299 }
300 fn reset_occurrences(&mut self, _table: &str) -> StorageBackendResult<()> {
302 Ok(())
303 }
304 fn fence_record(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
306 Ok(())
307 }
308 fn replace_statistics_maintenance(
310 &mut self,
311 key: &[u8],
312 value: &[u8],
313 ) -> StorageBackendResult<()> {
314 self.put(key, value)
315 }
316 fn graph_mutation(
318 &mut self,
319 _mutation: crate::mvcc::GraphMutation<'_>,
320 ) -> StorageBackendResult<()> {
321 Ok(())
322 }
323 fn preview_graph_invalidation(
325 &mut self,
326 key: &[u8],
327 value: Option<&[u8]>,
328 ) -> StorageBackendResult<()> {
329 match value {
330 Some(value) => self.put(key, value),
331 None => self.delete(key),
332 }
333 }
334 fn replace_graph_cache(
336 &mut self,
337 key: &[u8],
338 value: Option<&[u8]>,
339 ) -> StorageBackendResult<()> {
340 match value {
341 Some(value) => self.put(key, value),
342 None => self.delete(key),
343 }
344 }
345 fn commit(self: Box<Self>) -> StorageBackendResult<()>;
346}
347
348pub use vector_index::guards::KeyValueVectorFieldGuards;
349
350pub(crate) fn diskann_tombstone_prefixes() -> [&'static [u8]; 5] {
351 [
352 diskann::READ_PREFIX,
353 vector_index::origin::ROOT,
354 vector_index::origin::journal::ROOT,
355 vector_index::guards::ROOT,
356 vector_index::origin::populations::ROOT,
357 ]
358}
359
360pub trait KeyValueStore: Send + Sync {
362 fn resource_leases(&self) -> Option<&dyn crate::mvcc::ResourceLeaseProvider> {
364 None
365 }
366
367 fn auxiliary_encryption_key(&self) -> Option<crate::StorageEncryptionKey> {
369 None
370 }
371
372 fn retention_control(&self) -> Option<crate::read_control::StorageReadControl> {
374 None
375 }
376
377 fn notification_publications(
379 &self,
380 ) -> Option<&dyn crate::notifications::NotificationPublicationStore> {
381 None
382 }
383
384 fn serializable_session(&self) -> Option<&dyn crate::mvcc::SerializableSession> {
386 None
387 }
388
389 fn reclaim_obsolete(&self) -> StorageBackendResult<()> {
391 if self.transaction_model().is_versioned() {
392 return Err(StorageBackendError::Other(
393 "versioned KeyValue maintenance is not implemented by this store".into(),
394 ));
395 }
396 Ok(())
397 }
398
399 fn vacuum(&self) -> StorageBackendResult<()> {
401 self.reclaim_obsolete()
402 }
403
404 fn write_cancellation(&self) -> Option<uqa_core::CancellationToken> {
406 None
407 }
408
409 fn open_controlled_session(
411 &self,
412 _control: &crate::read_control::StorageReadControl,
413 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
414 Err(StorageBackendError::Other(
415 "controlled independent sessions are not implemented for this store".into(),
416 ))
417 }
418
419 fn open_session_with_cancellation(
421 &self,
422 cancellation: &uqa_core::CancellationToken,
423 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
424 cancellation.check()?;
425 if self.transaction_model().is_versioned() {
426 return Err(StorageBackendError::Other(
427 "cancellable independent KeyValue sessions are not implemented by this store"
428 .into(),
429 ));
430 }
431 self.open_session()
432 }
433
434 fn open_retained_read_session(
436 &self,
437 cancellation: &uqa_core::CancellationToken,
438 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
439 cancellation.check()?;
440 Err(StorageBackendError::Other(
441 "retained read sessions are not implemented by this KeyValue store".into(),
442 ))
443 }
444
445 fn transaction_model(&self) -> crate::StorageTransactionModel {
447 crate::StorageTransactionModel::ProviderSerialized
448 }
449
450 fn identifier_allocator(&self) -> Option<&dyn crate::mvcc::IdentifierAllocator> {
452 None
453 }
454
455 fn with_read_view(&self, _read: &mut KeyValueReadScope<'_>) -> StorageBackendResult<()> {
457 Err(StorageBackendError::Other(
458 "compound KeyValue reads are not supported by this store".into(),
459 ))
460 }
461
462 fn with_mutation(&self, _mutate: &mut KeyValueMutation<'_>) -> StorageBackendResult<()> {
464 Err(StorageBackendError::Other(
465 "atomic KeyValue evaluation is not supported by this store".into(),
466 ))
467 }
468
469 fn with_mutation_revision(
471 &self,
472 _prefixes: &[&[u8]],
473 mutate: &mut KeyValueMutation<'_>,
474 ) -> StorageBackendResult<Option<KeyValueReadRevision>> {
475 self.with_mutation(mutate)?;
476 Ok(None)
477 }
478
479 fn with_versioned_mutation(
481 &self,
482 _mutate: &mut KeyValueVersionedMutation<'_>,
483 ) -> StorageBackendResult<()> {
484 Err(StorageBackendError::Other(
485 "versioned KeyValue mutation origins are not supported by this store".into(),
486 ))
487 }
488
489 fn transaction_affinity(&self) -> Option<crate::StorageSessionAffinity> {
491 None
492 }
493
494 fn storage_identity(&self) -> StorageBackendResult<Option<PersistentStorageIdentity>> {
495 Ok(None)
496 }
497
498 fn open_session(&self) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
500 Err(StorageBackendError::Other(
501 "independent sessions are not implemented for this KeyValue store".into(),
502 ))
503 }
504
505 fn get(&self, key: &[u8]) -> StorageBackendResult<Option<Vec<u8>>>;
506 fn visit_value(
508 &self,
509 _key: &[u8],
510 control: &crate::read_control::StorageReadControl,
511 _visit: &mut crate::read_control::ValueReadVisitor<'_>,
512 ) -> StorageBackendResult<()> {
513 control.check()?;
514 Err(StorageBackendError::Other(
515 "controlled value reads are not supported by this KeyValue store".into(),
516 ))
517 }
518 fn visit_value_bounded(
520 &self,
521 _key: &[u8],
522 _max_bytes: usize,
523 control: &crate::read_control::StorageReadControl,
524 _visit: &mut crate::read_control::ValueReadVisitor<'_>,
525 ) -> StorageBackendResult<()> {
526 control.check()?;
527 Err(StorageBackendError::Other(
528 "size-bounded value reads are not supported by this KeyValue store".into(),
529 ))
530 }
531
532 fn visit_prefix_after(
534 &self,
535 _prefix: &[u8],
536 _after: Option<&[u8]>,
537 _limit: usize,
538 control: &crate::read_control::StorageReadControl,
539 _visit: &mut crate::read_control::KeyValueReadVisitor<'_>,
540 ) -> StorageBackendResult<()> {
541 control.check()?;
542 Err(StorageBackendError::Other(
543 "controlled prefix reads are not supported by this KeyValue store".into(),
544 ))
545 }
546 fn contains_prefix_budgeted(
548 &self,
549 prefix: &[u8],
550 control: &crate::read_control::StorageReadControl,
551 ) -> StorageBackendResult<bool> {
552 let mut found = false;
553 self.visit_prefix_after(prefix, None, 1, control, &mut |_, _| {
554 found = true;
555 Ok(())
556 })?;
557 control.check()?;
558 Ok(found)
559 }
560
561 fn contains_key(&self, key: &[u8]) -> StorageBackendResult<bool> {
562 self.get(key).map(|value| value.is_some())
563 }
564 fn put(&self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
565 fn delete(&self, key: &[u8]) -> StorageBackendResult<()>;
566 fn scan_prefix(&self, prefix: &[u8]) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>>;
567 fn scan_prefix_after(
571 &self,
572 prefix: &[u8],
573 after: Option<&[u8]>,
574 limit: usize,
575 ) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>> {
576 if limit == 0 {
577 return Ok(Vec::new());
578 }
579 Ok(self
580 .scan_prefix(prefix)?
581 .into_iter()
582 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
583 .take(limit)
584 .collect())
585 }
586 fn scan_prefix_keys_after(
591 &self,
592 prefix: &[u8],
593 after: Option<&[u8]>,
594 limit: usize,
595 ) -> StorageBackendResult<Vec<Vec<u8>>> {
596 if limit == 0 {
597 return Ok(Vec::new());
598 }
599 Ok(self
600 .scan_prefix(prefix)?
601 .into_iter()
602 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
603 .take(limit)
604 .map(|(key, _)| key)
605 .collect())
606 }
607 fn first_prefix_after(
608 &self,
609 prefix: &[u8],
610 after: Option<&[u8]>,
611 ) -> StorageBackendResult<Option<(Vec<u8>, Vec<u8>)>> {
612 Ok(self
613 .scan_prefix(prefix)?
614 .into_iter()
615 .find(|(key, _)| after.is_none_or(|after| key.as_slice() > after)))
616 }
617 fn delete_prefix(&self, prefix: &[u8]) -> StorageBackendResult<usize>;
618 fn batch(&self) -> Box<dyn KeyValueBatch + '_>;
619
620 fn begin_transaction(&self) -> StorageBackendResult<()> {
621 Err(StorageBackendError::Other(
622 "KeyValue transaction begin is not implemented for this store".into(),
623 ))
624 }
625
626 fn begin_read_transaction(&self) -> StorageBackendResult<()> {
627 self.begin_transaction()
628 }
629
630 fn begin_upgradeable_transaction(&self) -> StorageBackendResult<()> {
631 self.begin_transaction()
632 }
633
634 fn in_transaction(&self) -> bool;
635
636 fn transaction_has_written(&self) -> StorageBackendResult<bool>;
638
639 fn change_version(&self) -> StorageBackendResult<Option<u64>> {
640 Ok(None)
641 }
642
643 fn read_view_revision(&self) -> StorageBackendResult<Option<KeyValueReadRevision>> {
645 Ok(None)
646 }
647
648 fn completed_commit(&self) -> Option<crate::mvcc::CommitReceipt> {
650 None
651 }
652
653 fn change_version_monitor_is_nonblocking(&self) -> StorageBackendResult<bool> {
654 Ok(true)
655 }
656
657 fn pin_transaction_snapshot(&self) -> StorageBackendResult<()> {
658 Ok(())
659 }
660
661 fn refresh_transaction_snapshot(
663 &self,
664 _cancellation: &uqa_core::CancellationToken,
665 ) -> StorageBackendResult<()> {
666 Err(StorageBackendError::Other(
667 "transaction snapshot refresh is not supported by this KeyValue store".into(),
668 ))
669 }
670
671 fn commit_transaction(&self) -> StorageBackendResult<()> {
672 Err(StorageBackendError::Other(
673 "KeyValue transaction commit is not implemented for this store".into(),
674 ))
675 }
676
677 fn rollback_transaction(&self) -> StorageBackendResult<()> {
678 Err(StorageBackendError::Other(
679 "KeyValue transaction rollback is not implemented for this store".into(),
680 ))
681 }
682
683 fn savepoint(&self, _name: &str) -> StorageBackendResult<()> {
684 Err(StorageBackendError::Other(
685 "KeyValue savepoints are not implemented for this store".into(),
686 ))
687 }
688
689 fn release_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
690 Err(StorageBackendError::Other(
691 "KeyValue savepoint release is not implemented for this store".into(),
692 ))
693 }
694
695 fn rollback_to_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
696 Err(StorageBackendError::Other(
697 "KeyValue savepoint rollback is not implemented for this store".into(),
698 ))
699 }
700}
701
702mod btree_index;
703mod codec;
704pub mod conformance;
705mod document_store;
706mod hnsw_index;
707mod hnsw_persistence;
708mod index_keys;
709mod inverted_index;
710mod ivf_index;
711mod ivf_persistence;
712mod memory_store;
713pub mod occurrence_format;
714mod occurrence_keys;
715mod storage_backend;
716mod vector_index;
717
718pub use codec::prefix_upper_bound;
719pub use document_store::KeyValueDocumentStore;
720pub use hnsw_index::KeyValueHNSWIndex;
721pub use inverted_index::{KeyValueInvertedIndex, OccurrenceStorage};
722pub use ivf_index::KeyValueIVFIndex;
723pub use memory_store::MemoryKeyValueStore;
724pub use storage_backend::KeyValueStorageBackend;
725pub use vector_index::{
726 DiskANNCanonicalVectorVisitor, KeyValueDiskANNCanonical, KeyValueDiskANNHandle,
727 KeyValueDiskANNPopulationRecords, KeyValueVectorIndex, RetainedDiskANNCanonical,
728};
729
730#[cfg(test)]
731mod tests;