1use std::collections::HashMap;
74use std::path::Path;
75use std::sync::{Arc, RwLock};
76
77use tracing::{debug, info, instrument, warn};
78
79pub mod logging;
80mod security;
81
82pub use rustlite_core::index::{BTreeIndex, HashIndex, Index, IndexInfo, IndexManager, IndexType};
84pub use rustlite_core::{Error, Result};
85
86pub use rustlite_core::transaction::{
88 IsolationLevel, MVCCStorage, Timestamp, Transaction, TransactionId, TransactionManager,
89 VersionChain, VersionedValue,
90};
91
92pub use rustlite_core::query::{
94 Column, ExecutionContext, Executor, Lexer, Parser, PhysicalPlan, Planner, Query, Row, Value,
95};
96
97pub use rustlite_wal::{
99 RecoveryManager, RecoveryStats, SyncMode, WalConfig, WalManager, WalReader, WalRecord,
100};
101
102pub use rustlite_storage::{
104 CompactionConfig, CompactionStats, CompactionWorker, Manifest, Memtable, MemtableEntry,
105 SSTableEntry, SSTableMeta, SSTableReader, SSTableWriter, StorageConfig, StorageEngine,
106 StorageStats,
107};
108
109pub use rustlite_snapshot::{
111 SnapshotConfig, SnapshotFile, SnapshotManager, SnapshotMeta, SnapshotType,
112};
113
114pub const VERSION: &str = env!("CARGO_PKG_VERSION");
116
117enum StorageBackend {
119 Memory(RwLock<HashMap<Vec<u8>, Vec<u8>>>),
121 Persistent(StorageEngine),
123}
124
125struct DatabaseInner {
127 storage: StorageBackend,
129 indexes: RwLock<IndexManager>,
131 transaction_manager: Option<Arc<TransactionManager>>,
133}
134
135#[derive(Clone)]
156pub struct Database {
157 inner: Arc<DatabaseInner>,
158}
159
160impl Database {
161 pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
180 let path_ref = path.as_ref();
181 info!(path = ?path_ref, "Opening RustLite database");
182
183 let engine = StorageEngine::open(path)?;
184 let mvcc_storage = Arc::new(MVCCStorage::new());
185 let tx_manager = TransactionManager::new(mvcc_storage);
186
187 Ok(Database {
188 inner: Arc::new(DatabaseInner {
189 storage: StorageBackend::Persistent(engine),
190 indexes: RwLock::new(IndexManager::new()),
191 transaction_manager: Some(tx_manager),
192 }),
193 })
194 }
195
196 pub fn open_with_config<P: AsRef<Path>>(path: P, config: StorageConfig) -> Result<Self> {
203 let engine = StorageEngine::open_with_config(path, config)?;
204 let mvcc_storage = Arc::new(MVCCStorage::new());
205 let tx_manager = TransactionManager::new(mvcc_storage);
206
207 Ok(Database {
208 inner: Arc::new(DatabaseInner {
209 storage: StorageBackend::Persistent(engine),
210 indexes: RwLock::new(IndexManager::new()),
211 transaction_manager: Some(tx_manager),
212 }),
213 })
214 }
215
216 pub fn in_memory() -> Result<Self> {
232 info!("Creating in-memory RustLite database");
233
234 let mvcc_storage = Arc::new(MVCCStorage::new());
235 let tx_manager = TransactionManager::new(mvcc_storage);
236
237 Ok(Database {
238 inner: Arc::new(DatabaseInner {
239 storage: StorageBackend::Memory(RwLock::new(HashMap::new())),
240 indexes: RwLock::new(IndexManager::new()),
241 transaction_manager: Some(tx_manager),
242 }),
243 })
244 }
245
246 #[deprecated(
250 since = "0.2.0",
251 note = "Use `Database::open()` for persistent storage or `Database::in_memory()` for temporary storage"
252 )]
253 pub fn new() -> Result<Self> {
254 Self::in_memory()
255 }
256
257 #[instrument(skip(self, key, value), fields(key_len = key.len(), value_len = value.len()))]
277 pub fn put(&self, key: &[u8], value: &[u8]) -> Result<()> {
278 security::validate_key(key)?;
280 security::validate_value(value)?;
281
282 debug!("Writing key-value pair");
283
284 match &self.inner.storage {
285 StorageBackend::Memory(store) => {
286 let mut store = store.write().map_err(|_| Error::LockPoisoned)?;
287 store.insert(key.to_vec(), value.to_vec());
288 Ok(())
289 }
290 StorageBackend::Persistent(engine) => engine.put(key, value),
291 }
292 }
293
294 #[instrument(skip(self, key), fields(key_len = key.len()))]
317 pub fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>> {
318 security::validate_key(key)?;
320
321 debug!("Reading key");
322
323 match &self.inner.storage {
324 StorageBackend::Memory(store) => {
325 let store = store.read().map_err(|_| Error::LockPoisoned)?;
326 Ok(store.get(key).cloned())
327 }
328 StorageBackend::Persistent(engine) => engine.get(key),
329 }
330 }
331
332 #[instrument(skip(self, key), fields(key_len = key.len()))]
352 pub fn delete(&self, key: &[u8]) -> Result<bool> {
353 security::validate_key(key)?;
355
356 debug!("Deleting key");
357
358 match &self.inner.storage {
359 StorageBackend::Memory(store) => {
360 let mut store = store.write().map_err(|_| Error::LockPoisoned)?;
361 Ok(store.remove(key).is_some())
362 }
363 StorageBackend::Persistent(engine) => {
364 let existed = engine.get(key)?.is_some();
366 if existed {
367 engine.delete(key)?;
368 }
369 Ok(existed)
370 }
371 }
372 }
373
374 pub fn sync(&self) -> Result<()> {
390 match &self.inner.storage {
391 StorageBackend::Memory(_) => Ok(()),
392 StorageBackend::Persistent(engine) => engine.sync(),
393 }
394 }
395
396 pub fn is_persistent(&self) -> bool {
398 matches!(&self.inner.storage, StorageBackend::Persistent(_))
399 }
400
401 #[instrument(skip(self), fields(name = %name, index_type = ?index_type))]
423 pub fn create_index(&self, name: &str, index_type: IndexType) -> Result<()> {
424 security::validate_index_name(name)?;
426
427 info!("Creating index");
428
429 let mut indexes = self
430 .inner
431 .indexes
432 .write()
433 .map_err(|_| Error::LockPoisoned)?;
434 indexes.create_index(name, index_type)
435 }
436
437 pub fn drop_index(&self, name: &str) -> Result<bool> {
453 let mut indexes = self
454 .inner
455 .indexes
456 .write()
457 .map_err(|_| Error::LockPoisoned)?;
458 indexes.drop_index(name)
459 }
460
461 pub fn index_insert(&self, name: &str, key: &[u8], value: u64) -> Result<()> {
479 let mut indexes = self
480 .inner
481 .indexes
482 .write()
483 .map_err(|_| Error::LockPoisoned)?;
484 indexes.insert(name, key, value)
485 }
486
487 pub fn index_find(&self, name: &str, key: &[u8]) -> Result<Vec<u64>> {
503 let indexes = self.inner.indexes.read().map_err(|_| Error::LockPoisoned)?;
504 indexes.find(name, key)
505 }
506
507 pub fn index_remove(&self, name: &str, key: &[u8]) -> Result<bool> {
511 let mut indexes = self
512 .inner
513 .indexes
514 .write()
515 .map_err(|_| Error::LockPoisoned)?;
516 indexes.remove(name, key)
517 }
518
519 pub fn list_indexes(&self) -> Result<Vec<String>> {
535 let indexes = self.inner.indexes.read().map_err(|_| Error::LockPoisoned)?;
536 Ok(indexes
537 .list_indexes()
538 .iter()
539 .map(|s| s.to_string())
540 .collect())
541 }
542
543 pub fn index_info(&self) -> Result<Vec<IndexInfo>> {
561 let indexes = self.inner.indexes.read().map_err(|_| Error::LockPoisoned)?;
562 Ok(indexes.index_info())
563 }
564
565 #[instrument(skip(self, sql, context), fields(sql_len = sql.len()))]
600 pub fn query(&self, sql: &str, context: ExecutionContext) -> Result<Vec<Row>> {
601 security::validate_query(sql)?;
603
604 debug!(sql = %sql, "Executing query");
605
606 let mut parser =
608 Parser::new(sql).map_err(|e| Error::InvalidInput(format!("Parse error: {}", e)))?;
609 let query = parser
610 .parse()
611 .map_err(|e| Error::InvalidInput(format!("Parse error: {}", e)))?;
612
613 let planner = Planner::new();
615 let plan = planner
616 .plan(&query)
617 .map_err(|e| Error::InvalidInput(format!("Planning error: {}", e)))?;
618
619 let mut executor = Executor::new(context);
621 executor.execute(&plan)
622 }
623
624 pub fn prepare(&self, sql: &str) -> Result<PhysicalPlan> {
639 let mut parser =
640 Parser::new(sql).map_err(|e| Error::InvalidInput(format!("Parse error: {}", e)))?;
641 let query = parser
642 .parse()
643 .map_err(|e| Error::InvalidInput(format!("Parse error: {}", e)))?;
644
645 let planner = Planner::new();
646 planner
647 .plan(&query)
648 .map_err(|e| Error::InvalidInput(format!("Planning error: {}", e)))
649 }
650
651 pub fn execute_plan(&self, plan: &PhysicalPlan, context: ExecutionContext) -> Result<Vec<Row>> {
653 let mut executor = Executor::new(context);
654 executor.execute(plan)
655 }
656
657 #[instrument(skip(self), fields(isolation = ?isolation))]
683 pub fn begin_transaction(&self, isolation: IsolationLevel) -> Result<Transaction> {
684 info!("Beginning transaction");
685 if let Some(ref manager) = self.inner.transaction_manager {
686 manager.begin(isolation)
687 } else {
688 Err(Error::Transaction(
689 "Transaction support not initialized".into(),
690 ))
691 }
692 }
693
694 pub fn begin(&self) -> Result<Transaction> {
710 self.begin_transaction(IsolationLevel::default())
711 }
712
713 pub fn gc(&self) -> Result<()> {
729 if let Some(ref manager) = self.inner.transaction_manager {
730 manager.gc()
731 } else {
732 Ok(()) }
734 }
735}
736
737#[cfg(test)]
738mod tests {
739 use super::*;
740 use tempfile::tempdir;
741
742 #[test]
743 fn test_version() {
744 assert_eq!(VERSION, "0.7.0");
745 }
746
747 #[test]
748 fn test_in_memory_database() {
749 let db = Database::in_memory().unwrap();
750 db.put(b"key", b"value").unwrap();
751 assert_eq!(db.get(b"key").unwrap(), Some(b"value".to_vec()));
752 assert!(!db.is_persistent());
753 }
754
755 #[test]
756 fn test_persistent_database() {
757 let dir = tempdir().unwrap();
758 let db = Database::open(dir.path()).unwrap();
759
760 db.put(b"persist", b"data").unwrap();
761 assert_eq!(db.get(b"persist").unwrap(), Some(b"data".to_vec()));
762 assert!(db.is_persistent());
763 }
764
765 #[test]
766 fn test_persistence_across_reopens() {
767 let dir = tempdir().unwrap();
768
769 {
771 let db = Database::open(dir.path()).unwrap();
772 db.put(b"key1", b"value1").unwrap();
773 db.put(b"key2", b"value2").unwrap();
774 db.sync().unwrap();
775 }
776
777 {
779 let db = Database::open(dir.path()).unwrap();
780 assert_eq!(db.get(b"key1").unwrap(), Some(b"value1".to_vec()));
781 assert_eq!(db.get(b"key2").unwrap(), Some(b"value2".to_vec()));
782 }
783 }
784
785 #[test]
786 fn test_delete() {
787 let dir = tempdir().unwrap();
788 let db = Database::open(dir.path()).unwrap();
789
790 db.put(b"key", b"value").unwrap();
791 assert!(db.delete(b"key").unwrap());
792 assert_eq!(db.get(b"key").unwrap(), None);
793 assert!(!db.delete(b"key").unwrap()); }
795
796 #[test]
797 fn test_update() {
798 let db = Database::in_memory().unwrap();
799
800 db.put(b"counter", b"1").unwrap();
801 assert_eq!(db.get(b"counter").unwrap(), Some(b"1".to_vec()));
802
803 db.put(b"counter", b"2").unwrap();
804 assert_eq!(db.get(b"counter").unwrap(), Some(b"2".to_vec()));
805 }
806
807 #[test]
808 #[allow(deprecated)]
809 fn test_backward_compatibility() {
810 let db = Database::new().unwrap();
812 db.put(b"key", b"value").unwrap();
813 assert_eq!(db.get(b"key").unwrap(), Some(b"value".to_vec()));
814 }
815
816 #[test]
818 fn test_create_and_drop_index() {
819 let db = Database::in_memory().unwrap();
820
821 db.create_index("test_idx", IndexType::BTree).unwrap();
822 assert_eq!(db.list_indexes().unwrap().len(), 1);
823
824 assert!(db.drop_index("test_idx").unwrap());
825 assert_eq!(db.list_indexes().unwrap().len(), 0);
826 }
827
828 #[test]
829 fn test_btree_index_operations() {
830 let db = Database::in_memory().unwrap();
831 db.create_index("names", IndexType::BTree).unwrap();
832
833 db.index_insert("names", b"alice", 100).unwrap();
834 db.index_insert("names", b"bob", 101).unwrap();
835 db.index_insert("names", b"charlie", 102).unwrap();
836
837 assert_eq!(db.index_find("names", b"bob").unwrap(), vec![101]);
838
839 assert!(db.index_remove("names", b"bob").unwrap());
840 assert!(db.index_find("names", b"bob").unwrap().is_empty());
841 }
842
843 #[test]
844 fn test_hash_index_operations() {
845 let db = Database::in_memory().unwrap();
846 db.create_index("sessions", IndexType::Hash).unwrap();
847
848 db.index_insert("sessions", b"sess:abc", 500).unwrap();
849 db.index_insert("sessions", b"sess:def", 501).unwrap();
850
851 assert_eq!(db.index_find("sessions", b"sess:abc").unwrap(), vec![500]);
852 assert!(db
853 .index_find("sessions", b"nonexistent")
854 .unwrap()
855 .is_empty());
856 }
857
858 #[test]
859 fn test_index_info() {
860 let db = Database::in_memory().unwrap();
861 db.create_index("idx1", IndexType::BTree).unwrap();
862 db.create_index("idx2", IndexType::Hash).unwrap();
863
864 db.index_insert("idx1", b"key1", 1).unwrap();
865 db.index_insert("idx1", b"key2", 2).unwrap();
866 db.index_insert("idx2", b"key3", 3).unwrap();
867
868 let info = db.index_info().unwrap();
869 assert_eq!(info.len(), 2);
870 }
871
872 #[test]
873 fn test_simple_query() {
874 let db = Database::in_memory().unwrap();
875
876 let mut context = ExecutionContext::new();
877 context.data.insert(
878 "users".to_string(),
879 vec![
880 Row {
881 columns: vec![
882 Column {
883 name: "name".to_string(),
884 alias: None,
885 },
886 Column {
887 name: "age".to_string(),
888 alias: None,
889 },
890 ],
891 values: vec![Value::String("Alice".to_string()), Value::Integer(30)],
892 },
893 Row {
894 columns: vec![
895 Column {
896 name: "name".to_string(),
897 alias: None,
898 },
899 Column {
900 name: "age".to_string(),
901 alias: None,
902 },
903 ],
904 values: vec![Value::String("Bob".to_string()), Value::Integer(25)],
905 },
906 ],
907 );
908
909 let results = db.query("SELECT * FROM users", context).unwrap();
910 assert_eq!(results.len(), 2);
911 }
912
913 #[test]
914 fn test_query_with_where() {
915 let db = Database::in_memory().unwrap();
916
917 let mut context = ExecutionContext::new();
918 context.data.insert(
919 "users".to_string(),
920 vec![
921 Row {
922 columns: vec![
923 Column {
924 name: "name".to_string(),
925 alias: None,
926 },
927 Column {
928 name: "age".to_string(),
929 alias: None,
930 },
931 ],
932 values: vec![Value::String("Alice".to_string()), Value::Integer(30)],
933 },
934 Row {
935 columns: vec![
936 Column {
937 name: "name".to_string(),
938 alias: None,
939 },
940 Column {
941 name: "age".to_string(),
942 alias: None,
943 },
944 ],
945 values: vec![Value::String("Bob".to_string()), Value::Integer(25)],
946 },
947 ],
948 );
949
950 let results = db
951 .query("SELECT name FROM users WHERE age > 26", context)
952 .unwrap();
953 assert_eq!(results.len(), 1);
954 assert_eq!(results[0].values[0], Value::String("Alice".to_string()));
955 }
956
957 #[test]
958 fn test_query_with_limit() {
959 let db = Database::in_memory().unwrap();
960
961 let mut context = ExecutionContext::new();
962 context.data.insert(
963 "users".to_string(),
964 vec![
965 Row {
966 columns: vec![Column {
967 name: "name".to_string(),
968 alias: None,
969 }],
970 values: vec![Value::String("Alice".to_string())],
971 },
972 Row {
973 columns: vec![Column {
974 name: "name".to_string(),
975 alias: None,
976 }],
977 values: vec![Value::String("Bob".to_string())],
978 },
979 Row {
980 columns: vec![Column {
981 name: "name".to_string(),
982 alias: None,
983 }],
984 values: vec![Value::String("Charlie".to_string())],
985 },
986 ],
987 );
988
989 let results = db.query("SELECT * FROM users LIMIT 2", context).unwrap();
990 assert_eq!(results.len(), 2);
991 }
992
993 #[test]
994 fn test_prepare_and_execute() {
995 let db = Database::in_memory().unwrap();
996 let plan = db.prepare("SELECT * FROM users WHERE age > 18").unwrap();
997
998 let mut context = ExecutionContext::new();
999 context.data.insert(
1000 "users".to_string(),
1001 vec![Row {
1002 columns: vec![
1003 Column {
1004 name: "name".to_string(),
1005 alias: None,
1006 },
1007 Column {
1008 name: "age".to_string(),
1009 alias: None,
1010 },
1011 ],
1012 values: vec![Value::String("Alice".to_string()), Value::Integer(30)],
1013 }],
1014 );
1015
1016 let results = db.execute_plan(&plan, context).unwrap();
1017 assert_eq!(results.len(), 1);
1018 }
1019
1020 #[test]
1022 fn test_transaction_basic() {
1023 let db = Database::in_memory().unwrap();
1024
1025 let mut txn = db.begin().unwrap();
1026 txn.put(b"key1".to_vec(), b"value1".to_vec()).unwrap();
1027 txn.put(b"key2".to_vec(), b"value2".to_vec()).unwrap();
1028 txn.commit().unwrap();
1029
1030 let txn2 = db.begin().unwrap();
1032 assert_eq!(txn2.get(b"key1").unwrap(), Some(b"value1".to_vec()));
1033 assert_eq!(txn2.get(b"key2").unwrap(), Some(b"value2".to_vec()));
1034 }
1035
1036 #[test]
1037 fn test_transaction_isolation() {
1038 let db = Database::in_memory().unwrap();
1039
1040 let mut txn1 = db.begin().unwrap();
1042 txn1.put(b"counter".to_vec(), b"1".to_vec()).unwrap();
1043 txn1.commit().unwrap();
1044
1045 let txn2 = db.begin().unwrap();
1047 assert_eq!(txn2.get(b"counter").unwrap(), Some(b"1".to_vec()));
1048
1049 let mut txn3 = db.begin().unwrap();
1051 txn3.put(b"counter".to_vec(), b"2".to_vec()).unwrap();
1052 txn3.commit().unwrap();
1053
1054 assert_eq!(txn2.get(b"counter").unwrap(), Some(b"1".to_vec()));
1056 }
1057
1058 #[test]
1059 fn test_transaction_rollback() {
1060 let db = Database::in_memory().unwrap();
1061
1062 let mut txn1 = db.begin().unwrap();
1064 txn1.put(b"key1".to_vec(), b"original".to_vec()).unwrap();
1065 txn1.commit().unwrap();
1066
1067 let mut txn2 = db.begin().unwrap();
1069 txn2.put(b"key1".to_vec(), b"updated".to_vec()).unwrap();
1070 txn2.rollback().unwrap();
1071
1072 let txn3 = db.begin().unwrap();
1074 assert_eq!(txn3.get(b"key1").unwrap(), Some(b"original".to_vec()));
1075 }
1076
1077 #[test]
1078 fn test_transaction_delete() {
1079 let db = Database::in_memory().unwrap();
1080
1081 let mut txn1 = db.begin().unwrap();
1083 txn1.put(b"temp".to_vec(), b"data".to_vec()).unwrap();
1084 txn1.commit().unwrap();
1085
1086 let mut txn2 = db.begin().unwrap();
1088 txn2.delete(b"temp").unwrap();
1089 txn2.commit().unwrap();
1090
1091 let txn3 = db.begin().unwrap();
1093 assert_eq!(txn3.get(b"temp").unwrap(), None);
1094 }
1095
1096 #[test]
1097 fn test_transaction_scan() {
1098 let db = Database::in_memory().unwrap();
1099
1100 let mut txn = db.begin().unwrap();
1102 txn.put(b"user:1".to_vec(), b"alice".to_vec()).unwrap();
1103 txn.put(b"user:2".to_vec(), b"bob".to_vec()).unwrap();
1104 txn.put(b"post:1".to_vec(), b"post1".to_vec()).unwrap();
1105 txn.commit().unwrap();
1106
1107 let txn2 = db.begin().unwrap();
1109 let results = txn2.scan(b"user:").unwrap();
1110 assert_eq!(results.len(), 2);
1111 }
1112
1113 #[test]
1114 fn test_transaction_with_index() {
1115 let db = Database::in_memory().unwrap();
1116 db.create_index("user_idx", IndexType::Hash).unwrap();
1117
1118 let mut txn = db.begin().unwrap();
1120 txn.put(b"user:1".to_vec(), b"alice@example.com".to_vec())
1121 .unwrap();
1122 txn.commit().unwrap();
1123
1124 db.index_insert("user_idx", b"alice@example.com", 1)
1126 .unwrap();
1127
1128 let txn2 = db.begin().unwrap();
1130 let ids = db.index_find("user_idx", b"alice@example.com").unwrap();
1131 assert_eq!(ids, vec![1]);
1132
1133 assert_eq!(
1135 txn2.get(b"user:1").unwrap(),
1136 Some(b"alice@example.com".to_vec())
1137 );
1138 }
1139
1140 #[test]
1141 fn test_concurrent_transaction_isolation() {
1142 use std::sync::Arc;
1143 use std::thread;
1144
1145 let db = Arc::new(Database::in_memory().unwrap());
1146
1147 let mut setup = db.begin().unwrap();
1149 setup.put(b"balance".to_vec(), b"1000".to_vec()).unwrap();
1150 setup.commit().unwrap();
1151
1152 let db1 = db.clone();
1154 let handle1 = thread::spawn(move || {
1155 let txn = db1.begin().unwrap();
1156 let balance1_bytes = txn.get(b"balance").unwrap().unwrap();
1157 let balance1 = String::from_utf8_lossy(&balance1_bytes);
1158 thread::sleep(std::time::Duration::from_millis(10));
1159 let balance2_bytes = txn.get(b"balance").unwrap().unwrap();
1160 let balance2 = String::from_utf8_lossy(&balance2_bytes);
1161 assert_eq!(balance1, balance2); balance1.to_string()
1163 });
1164
1165 let db2 = db.clone();
1167 let handle2 = thread::spawn(move || {
1168 thread::sleep(std::time::Duration::from_millis(5));
1169 let mut txn = db2.begin().unwrap();
1170 txn.put(b"balance".to_vec(), b"2000".to_vec()).unwrap();
1171 txn.commit().unwrap();
1172 });
1173
1174 let balance_seen = handle1.join().unwrap();
1175 handle2.join().unwrap();
1176
1177 assert_eq!(balance_seen, "1000");
1179
1180 let final_txn = db.begin().unwrap();
1182 let final_balance_bytes = final_txn.get(b"balance").unwrap().unwrap();
1183 let final_balance = String::from_utf8_lossy(&final_balance_bytes);
1184 assert_eq!(final_balance, "2000");
1185 }
1186
1187 #[test]
1188 fn test_transaction_error_handling() {
1189 let db = Database::in_memory().unwrap();
1190
1191 let mut txn = db.begin().unwrap();
1193 txn.put(b"key".to_vec(), b"value".to_vec()).unwrap();
1194 txn.commit().unwrap();
1195
1196 }
1199
1200 #[test]
1201 fn test_transaction_with_query() {
1202 let db = Database::in_memory().unwrap();
1203
1204 let mut txn = db.begin().unwrap();
1206 txn.put(b"user:1:name".to_vec(), b"Alice".to_vec()).unwrap();
1207 txn.put(b"user:1:age".to_vec(), b"30".to_vec()).unwrap();
1208 txn.put(b"user:2:name".to_vec(), b"Bob".to_vec()).unwrap();
1209 txn.put(b"user:2:age".to_vec(), b"25".to_vec()).unwrap();
1210 txn.commit().unwrap();
1211
1212 let query_txn = db.begin().unwrap();
1214 let name = query_txn.get(b"user:1:name").unwrap();
1215 assert_eq!(name, Some(b"Alice".to_vec()));
1216 }
1217
1218 #[test]
1219 fn test_garbage_collection() {
1220 let db = Database::in_memory().unwrap();
1221
1222 for i in 0..10 {
1224 let mut txn = db.begin().unwrap();
1225 txn.put(b"key".to_vec(), format!("version{}", i).into_bytes())
1226 .unwrap();
1227 txn.commit().unwrap();
1228 }
1229
1230 db.gc().unwrap();
1232
1233 let txn = db.begin().unwrap();
1235 assert_eq!(txn.get(b"key").unwrap(), Some(b"version9".to_vec()));
1236 }
1237
1238 #[test]
1239 fn test_persistent_transactions() {
1240 let dir = tempdir().unwrap();
1241 let path = dir.path();
1242
1243 {
1245 let db = Database::open(path).unwrap();
1246 let mut txn = db.begin().unwrap();
1247 txn.put(b"persistent_key".to_vec(), b"persistent_value".to_vec())
1248 .unwrap();
1249 txn.commit().unwrap();
1250
1251 db.put(b"direct_key", b"direct_value").unwrap();
1253 db.sync().unwrap();
1254 }
1255
1256 {
1258 let db = Database::open(path).unwrap();
1259 assert_eq!(
1261 db.get(b"direct_key").unwrap(),
1262 Some(b"direct_value".to_vec())
1263 );
1264
1265 }
1268 }
1269
1270 #[test]
1271 fn test_transaction_with_large_dataset() {
1272 let db = Database::in_memory().unwrap();
1273
1274 let mut txn = db.begin().unwrap();
1276 for i in 0..1000 {
1277 let key = format!("key:{:04}", i);
1278 let value = format!("value:{}", i);
1279 txn.put(key.into_bytes(), value.into_bytes()).unwrap();
1280 }
1281 txn.commit().unwrap();
1282
1283 let verify_txn = db.begin().unwrap();
1285 for i in 0..1000 {
1286 let key = format!("key:{:04}", i);
1287 let expected_value = format!("value:{}", i);
1288 assert_eq!(
1289 verify_txn.get(&key.into_bytes()).unwrap(),
1290 Some(expected_value.into_bytes())
1291 );
1292 }
1293 }
1294
1295 #[test]
1296 fn test_mixed_transaction_and_direct_operations() {
1297 let db = Database::in_memory().unwrap();
1298
1299 db.put(b"direct", b"value1").unwrap();
1301
1302 let mut txn = db.begin().unwrap();
1304 txn.put(b"txn".to_vec(), b"value2".to_vec()).unwrap();
1305 txn.commit().unwrap();
1306
1307 assert_eq!(db.get(b"direct").unwrap(), Some(b"value1".to_vec()));
1309
1310 let read_txn = db.begin().unwrap();
1311 assert_eq!(read_txn.get(b"txn").unwrap(), Some(b"value2".to_vec()));
1312 }
1313
1314 #[test]
1315 fn test_serializable_isolation() {
1316 let db = Database::in_memory().unwrap();
1317
1318 let mut setup = db.begin().unwrap();
1320 setup.put(b"counter".to_vec(), b"0".to_vec()).unwrap();
1321 setup.commit().unwrap();
1322
1323 let txn = db.begin_transaction(IsolationLevel::Serializable).unwrap();
1325 assert_eq!(txn.isolation_level(), IsolationLevel::Serializable);
1326
1327 let value = txn.get(b"counter").unwrap();
1328 assert_eq!(value, Some(b"0".to_vec()));
1329 }
1330
1331 #[test]
1332 fn test_multiple_isolation_levels() {
1333 let db = Database::in_memory().unwrap();
1334
1335 let _txn1 = db
1337 .begin_transaction(IsolationLevel::ReadUncommitted)
1338 .unwrap();
1339 let _txn2 = db.begin_transaction(IsolationLevel::ReadCommitted).unwrap();
1340 let _txn3 = db
1341 .begin_transaction(IsolationLevel::RepeatableRead)
1342 .unwrap();
1343 let _txn4 = db.begin_transaction(IsolationLevel::Serializable).unwrap();
1344 }
1345}