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 graph_commit;
33mod table_owners;
34pub use graph_commit::KeyValueGraphRecords;
35mod hnsw_records;
36mod index_view;
37mod ivf_records;
38mod maintenance_records;
39mod notification_records;
40pub use notification_records::KeyValueNotificationRecords;
41pub(crate) mod record_json;
42pub use maintenance_records::KeyValueMaintenanceRecords;
43mod vector_records;
44pub use hnsw_records::KeyValueHNSWRecords;
45pub use ivf_records::KeyValueIVFRecords;
46pub(crate) mod occurrence_records;
47pub use occurrence_records::KeyValueOccurrenceRecords;
48mod view;
49pub use view::{KeyValueMutation, KeyValueRead, KeyValueReadRevision, KeyValueReadScope};
50
51const TAG_METADATA: u8 = b'm';
52const TAG_TABLE: u8 = b't';
53const TAG_MODEL: u8 = b'M';
54const TAG_SCORING_PARAMS: u8 = b'S';
55const TAG_NAMED_GRAPH: u8 = b'g';
56const TAG_VERTEX: u8 = b'V';
57const TAG_EDGE: u8 = b'E';
58const TAG_GRAPH_MEMBERSHIP: u8 = b'G';
59const TAG_GRAPH_LOOKUP: u8 = b'J';
60const TAG_ANALYZER: u8 = b'a';
61const TAG_ANALYZER_DESCRIPTOR: u8 = b'D';
62const TAG_FIELD_ANALYZER_BINDING: u8 = b'U';
63const TAG_TABLE_FIELD_ANALYZER: u8 = b'A';
64const TAG_FOREIGN_SERVER: u8 = b'F';
65const TAG_FOREIGN_TABLE: u8 = b'T';
66const TAG_CATALOG_INDEX: u8 = b'C';
67const TAG_PATH_INDEX: u8 = b'P';
68const TAG_PATH_INDEX_DATA: u8 = b'Q';
69const TAG_COLUMN_STATS: u8 = b'c';
70const TAG_SCHEMA: u8 = b's';
71const TAG_SEQUENCE: u8 = b'q';
72const TAG_RELATION: u8 = b'R';
73const TAG_VIEW: u8 = b'w';
74const TAG_DOCUMENT: u8 = b'd';
75const TAG_POSTING: u8 = b'p';
76const TAG_OCCURRENCE_INDEX: u8 = b'e';
77const TAG_POSTING_CLUSTER_SCORE: u8 = b'k';
78const TAG_POSTING_CLUSTER_POSITIONS: u8 = b'o';
79const TAG_POSTING_DOCUMENT: u8 = b'x';
80const TAG_DOC_LENGTH: u8 = b'l';
81const TAG_FIELD_STATS: u8 = b'f';
82const TAG_REVERSE_POSTING: u8 = b'r';
83const TAG_VECTOR: u8 = b'v';
84const TAG_BTREE_INDEX: u8 = b'B';
85const TAG_BTREE_ENTRY: u8 = b'b';
86const TAG_NAMED_BTREE_INDEX: u8 = b'N';
87const TAG_NAMED_BTREE_ENTRY: u8 = b'n';
88const TAG_IVF_METADATA: u8 = b'I';
89const TAG_IVF_CENTROID: u8 = b'i';
90const TAG_IVF_ASSIGNMENT: u8 = b'j';
91const TAG_HNSW_METADATA: u8 = b'H';
92const TAG_HNSW_NODE: u8 = b'h';
93
94const DOCUMENT_VALUE_V1_PREFIX: &[u8] = b"\0uqa-document-json-v1\0";
99const DOCUMENT_VALUE_V2_PREFIX: &[u8] = b"\0uqa-document-record-v2\0";
100
101#[derive(Debug, Clone)]
102enum KeyValueBatchOperation {
103 Put(Vec<u8>, Vec<u8>),
104 Delete(Vec<u8>),
105 DeletePrefix(Vec<u8>),
106}
107
108pub trait KeyValueBatch {
110 fn serializable_participant(&self) -> Option<crate::mvcc::SerializableTransactionId> {
112 None
113 }
114 fn observe_serializable_write(
116 &mut self,
117 _predicate: crate::mvcc::SerializablePredicate<'_>,
118 ) -> StorageBackendResult<()> {
119 Err(StorageBackendError::Other(
120 "atomic serializable write observations are not supported".into(),
121 ))
122 }
123 fn require_unchanged(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
125 Err(StorageBackendError::Other(
126 "commit-time record requirements are not supported".into(),
127 ))
128 }
129 fn touch_marker(&mut self, _key: &[u8], _value: &[u8]) -> StorageBackendResult<()> {
131 Err(StorageBackendError::Other(
132 "mergeable revision markers are not supported".into(),
133 ))
134 }
135 fn observe_identifier(&mut self, _namespace: &[u8], _value: u64) -> StorageBackendResult<()> {
137 Err(StorageBackendError::Other(
138 "durable identifier observations are not supported".into(),
139 ))
140 }
141 fn inherit_identifiers(&mut self, _from: &[u8], _to: &[u8]) -> StorageBackendResult<()> {
143 Err(StorageBackendError::Other(
144 "durable identifier inheritance is not supported".into(),
145 ))
146 }
147 fn put(&mut self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
148 fn delete(&mut self, key: &[u8]) -> StorageBackendResult<()>;
149 fn delete_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()>;
150 fn ivf_mutation(
152 &mut self,
153 _metadata: &[u8],
154 _mutation: crate::ivf_index::IVFMutation<'_>,
155 ) -> StorageBackendResult<()> {
156 Ok(())
157 }
158 fn preview_ivf_record(&mut self, key: &[u8], value: Option<&[u8]>) -> StorageBackendResult<()> {
160 match value {
161 Some(value) => self.put(key, value),
162 None => self.delete(key),
163 }
164 }
165 fn preview_ivf_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
166 self.delete_prefix(prefix)
167 }
168 fn fence_ivf_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
170 Ok(())
171 }
172 fn hnsw_mutation(
174 &mut self,
175 _metadata: &[u8],
176 _mutation: crate::hnsw_index::HNSWMutation<'_>,
177 ) -> StorageBackendResult<()> {
178 Ok(())
179 }
180 fn preview_hnsw_record(
182 &mut self,
183 key: &[u8],
184 value: Option<&[u8]>,
185 ) -> StorageBackendResult<()> {
186 match value {
187 Some(value) => self.put(key, value),
188 None => self.delete(key),
189 }
190 }
191 fn preview_hnsw_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
192 self.delete_prefix(prefix)
193 }
194 fn fence_hnsw_prefix(&mut self, _prefix: &[u8]) -> StorageBackendResult<()> {
196 Ok(())
197 }
198 fn replace_occurrence_record(
200 &mut self,
201 key: &[u8],
202 value: Option<&[u8]>,
203 ) -> StorageBackendResult<()> {
204 match value {
205 Some(value) => self.put(key, value),
206 None => self.delete(key),
207 }
208 }
209 fn invalidate_occurrence_prefix(&mut self, prefix: &[u8]) -> StorageBackendResult<()> {
211 self.delete_prefix(prefix)
212 }
213 fn occurrence_document(&mut self, _table: &str, _document: DocId) -> StorageBackendResult<()> {
215 Ok(())
216 }
217 fn reset_occurrences(&mut self, _table: &str) -> StorageBackendResult<()> {
219 Ok(())
220 }
221 fn fence_record(&mut self, _key: &[u8]) -> StorageBackendResult<()> {
223 Ok(())
224 }
225 fn replace_statistics_maintenance(
227 &mut self,
228 key: &[u8],
229 value: &[u8],
230 ) -> StorageBackendResult<()> {
231 self.put(key, value)
232 }
233 fn graph_mutation(
235 &mut self,
236 _mutation: crate::mvcc::GraphMutation<'_>,
237 ) -> StorageBackendResult<()> {
238 Ok(())
239 }
240 fn preview_graph_invalidation(
242 &mut self,
243 key: &[u8],
244 value: Option<&[u8]>,
245 ) -> StorageBackendResult<()> {
246 match value {
247 Some(value) => self.put(key, value),
248 None => self.delete(key),
249 }
250 }
251 fn replace_graph_cache(
253 &mut self,
254 key: &[u8],
255 value: Option<&[u8]>,
256 ) -> StorageBackendResult<()> {
257 match value {
258 Some(value) => self.put(key, value),
259 None => self.delete(key),
260 }
261 }
262 fn commit(self: Box<Self>) -> StorageBackendResult<()>;
263}
264
265pub trait KeyValueStore: Send + Sync {
267 fn auxiliary_encryption_key(&self) -> Option<crate::StorageEncryptionKey> {
269 None
270 }
271
272 fn retention_control(&self) -> Option<crate::read_control::StorageReadControl> {
274 None
275 }
276
277 fn notification_publications(
279 &self,
280 ) -> Option<&dyn crate::notifications::NotificationPublicationStore> {
281 None
282 }
283
284 fn serializable_session(&self) -> Option<&dyn crate::mvcc::SerializableSession> {
286 None
287 }
288
289 fn vacuum(&self) -> StorageBackendResult<()> {
291 if self.transaction_model().is_versioned() {
292 return Err(StorageBackendError::Other(
293 "versioned KeyValue maintenance is not implemented by this store".into(),
294 ));
295 }
296 Ok(())
297 }
298
299 fn write_cancellation(&self) -> Option<uqa_core::CancellationToken> {
301 None
302 }
303
304 fn open_session_with_cancellation(
306 &self,
307 cancellation: &uqa_core::CancellationToken,
308 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
309 cancellation.check()?;
310 if self.transaction_model().is_versioned() {
311 return Err(StorageBackendError::Other(
312 "cancellable independent KeyValue sessions are not implemented by this store"
313 .into(),
314 ));
315 }
316 self.open_session()
317 }
318
319 fn open_retained_read_session(
321 &self,
322 cancellation: &uqa_core::CancellationToken,
323 ) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
324 cancellation.check()?;
325 Err(StorageBackendError::Other(
326 "retained read sessions are not implemented by this KeyValue store".into(),
327 ))
328 }
329
330 fn transaction_model(&self) -> crate::StorageTransactionModel {
332 crate::StorageTransactionModel::ProviderSerialized
333 }
334
335 fn identifier_allocator(&self) -> Option<&dyn crate::mvcc::IdentifierAllocator> {
337 None
338 }
339
340 fn with_read_view(&self, _read: &mut KeyValueReadScope<'_>) -> StorageBackendResult<()> {
342 Err(StorageBackendError::Other(
343 "compound KeyValue reads are not supported by this store".into(),
344 ))
345 }
346
347 fn with_mutation(&self, _mutate: &mut KeyValueMutation<'_>) -> StorageBackendResult<()> {
349 Err(StorageBackendError::Other(
350 "atomic KeyValue evaluation is not supported by this store".into(),
351 ))
352 }
353
354 fn transaction_affinity(&self) -> Option<crate::StorageSessionAffinity> {
356 None
357 }
358
359 fn storage_identity(&self) -> StorageBackendResult<Option<PersistentStorageIdentity>> {
360 Ok(None)
361 }
362
363 fn open_session(&self) -> StorageBackendResult<Arc<dyn KeyValueStore>> {
365 Err(StorageBackendError::Other(
366 "independent sessions are not implemented for this KeyValue store".into(),
367 ))
368 }
369
370 fn get(&self, key: &[u8]) -> StorageBackendResult<Option<Vec<u8>>>;
371 fn visit_value(
373 &self,
374 _key: &[u8],
375 control: &crate::read_control::StorageReadControl,
376 _visit: &mut crate::read_control::ValueReadVisitor<'_>,
377 ) -> StorageBackendResult<()> {
378 control.check()?;
379 Err(StorageBackendError::Other(
380 "controlled value reads are not supported by this KeyValue store".into(),
381 ))
382 }
383 fn visit_prefix_after(
385 &self,
386 _prefix: &[u8],
387 _after: Option<&[u8]>,
388 _limit: usize,
389 control: &crate::read_control::StorageReadControl,
390 _visit: &mut crate::read_control::KeyValueReadVisitor<'_>,
391 ) -> StorageBackendResult<()> {
392 control.check()?;
393 Err(StorageBackendError::Other(
394 "controlled prefix reads are not supported by this KeyValue store".into(),
395 ))
396 }
397 fn contains_prefix_budgeted(
399 &self,
400 prefix: &[u8],
401 control: &crate::read_control::StorageReadControl,
402 ) -> StorageBackendResult<bool> {
403 let mut found = false;
404 self.visit_prefix_after(prefix, None, 1, control, &mut |_, _| {
405 found = true;
406 Ok(())
407 })?;
408 control.check()?;
409 Ok(found)
410 }
411
412 fn contains_key(&self, key: &[u8]) -> StorageBackendResult<bool> {
413 self.get(key).map(|value| value.is_some())
414 }
415 fn put(&self, key: &[u8], value: &[u8]) -> StorageBackendResult<()>;
416 fn delete(&self, key: &[u8]) -> StorageBackendResult<()>;
417 fn scan_prefix(&self, prefix: &[u8]) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>>;
418 fn scan_prefix_after(
422 &self,
423 prefix: &[u8],
424 after: Option<&[u8]>,
425 limit: usize,
426 ) -> StorageBackendResult<Vec<(Vec<u8>, Vec<u8>)>> {
427 if limit == 0 {
428 return Ok(Vec::new());
429 }
430 Ok(self
431 .scan_prefix(prefix)?
432 .into_iter()
433 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
434 .take(limit)
435 .collect())
436 }
437 fn scan_prefix_keys_after(
442 &self,
443 prefix: &[u8],
444 after: Option<&[u8]>,
445 limit: usize,
446 ) -> StorageBackendResult<Vec<Vec<u8>>> {
447 if limit == 0 {
448 return Ok(Vec::new());
449 }
450 Ok(self
451 .scan_prefix(prefix)?
452 .into_iter()
453 .filter(|(key, _)| after.is_none_or(|after| key.as_slice() > after))
454 .take(limit)
455 .map(|(key, _)| key)
456 .collect())
457 }
458 fn first_prefix_after(
459 &self,
460 prefix: &[u8],
461 after: Option<&[u8]>,
462 ) -> StorageBackendResult<Option<(Vec<u8>, Vec<u8>)>> {
463 Ok(self
464 .scan_prefix(prefix)?
465 .into_iter()
466 .find(|(key, _)| after.is_none_or(|after| key.as_slice() > after)))
467 }
468 fn delete_prefix(&self, prefix: &[u8]) -> StorageBackendResult<usize>;
469 fn batch(&self) -> Box<dyn KeyValueBatch + '_>;
470
471 fn begin_transaction(&self) -> StorageBackendResult<()> {
472 Err(StorageBackendError::Other(
473 "KeyValue transaction begin is not implemented for this store".into(),
474 ))
475 }
476
477 fn begin_read_transaction(&self) -> StorageBackendResult<()> {
478 self.begin_transaction()
479 }
480
481 fn begin_upgradeable_transaction(&self) -> StorageBackendResult<()> {
482 self.begin_transaction()
483 }
484
485 fn in_transaction(&self) -> bool;
486
487 fn transaction_has_written(&self) -> StorageBackendResult<bool>;
489
490 fn change_version(&self) -> StorageBackendResult<Option<u64>> {
491 Ok(None)
492 }
493
494 fn change_version_monitor_is_nonblocking(&self) -> StorageBackendResult<bool> {
495 Ok(true)
496 }
497
498 fn pin_transaction_snapshot(&self) -> StorageBackendResult<()> {
499 Ok(())
500 }
501
502 fn refresh_transaction_snapshot(
504 &self,
505 _cancellation: &uqa_core::CancellationToken,
506 ) -> StorageBackendResult<()> {
507 Err(StorageBackendError::Other(
508 "transaction snapshot refresh is not supported by this KeyValue store".into(),
509 ))
510 }
511
512 fn commit_transaction(&self) -> StorageBackendResult<()> {
513 Err(StorageBackendError::Other(
514 "KeyValue transaction commit is not implemented for this store".into(),
515 ))
516 }
517
518 fn rollback_transaction(&self) -> StorageBackendResult<()> {
519 Err(StorageBackendError::Other(
520 "KeyValue transaction rollback is not implemented for this store".into(),
521 ))
522 }
523
524 fn savepoint(&self, _name: &str) -> StorageBackendResult<()> {
525 Err(StorageBackendError::Other(
526 "KeyValue savepoints are not implemented for this store".into(),
527 ))
528 }
529
530 fn release_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
531 Err(StorageBackendError::Other(
532 "KeyValue savepoint release is not implemented for this store".into(),
533 ))
534 }
535
536 fn rollback_to_savepoint(&self, _name: &str) -> StorageBackendResult<()> {
537 Err(StorageBackendError::Other(
538 "KeyValue savepoint rollback is not implemented for this store".into(),
539 ))
540 }
541}
542
543mod btree_index;
544mod codec;
545pub mod conformance;
546mod document_store;
547mod hnsw_index;
548mod hnsw_persistence;
549mod index_keys;
550mod inverted_index;
551mod ivf_index;
552mod ivf_persistence;
553mod memory_store;
554pub mod occurrence_format;
555mod occurrence_keys;
556mod storage_backend;
557mod vector_index;
558
559pub use codec::prefix_upper_bound;
560pub use document_store::KeyValueDocumentStore;
561pub use hnsw_index::KeyValueHNSWIndex;
562pub use inverted_index::{KeyValueInvertedIndex, OccurrenceStorage};
563pub use ivf_index::KeyValueIVFIndex;
564pub use memory_store::MemoryKeyValueStore;
565pub use storage_backend::KeyValueStorageBackend;
566pub use vector_index::KeyValueVectorIndex;
567
568#[cfg(test)]
569mod tests;