1use crate::database_entry::DatabaseEntry;
5use crate::error::{NoxuError, Result};
6use crate::get::Get;
7use crate::lock_mode::LockMode;
8use crate::operation_status::OperationStatus;
9use crate::put::Put;
10use noxu_dbi::{CursorImpl, DbiError, GetMode, PutMode, SearchMode};
11
12#[inline]
20fn map_cursor_err(e: DbiError) -> NoxuError {
21 match e {
22 DbiError::EnvironmentFailure { .. } => NoxuError::from(e),
23 _ => NoxuError::OperationNotAllowed(e.to_string()),
24 }
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub enum CursorState {
30 NotInitialized,
32 Initialized,
34 Closed,
36}
37
38pub struct Cursor {
65 inner: CursorImpl,
67 state: CursorState,
69 read_only: bool,
71}
72
73impl Cursor {
74 pub(crate) fn from_impl(inner: CursorImpl, read_only: bool) -> Self {
78 Self { inner, state: CursorState::NotInitialized, read_only }
79 }
80
81 pub fn get(
108 &mut self,
109 key: &mut DatabaseEntry,
110 data: &mut DatabaseEntry,
111 get_type: Get,
112 _lock_mode: Option<LockMode>,
113 ) -> Result<OperationStatus> {
114 self.check_open()?;
115
116 if matches!(get_type, Get::Current) {
117 self.check_initialized()?;
118 }
119
120 let status = match get_type {
121 Get::Search => {
122 let key_bytes = key.get_data().unwrap_or(&[]);
127 self.inner
128 .search(key_bytes, None, SearchMode::Set)
129 .map_err(map_cursor_err)?
130 }
131 Get::SearchGte | Get::SearchRange => {
132 let key_bytes = key.get_data().unwrap_or(&[]);
133 self.inner
134 .search(key_bytes, None, SearchMode::SetRange)
135 .map_err(map_cursor_err)?
136 }
137 Get::First => self.inner.get_first().map_err(map_cursor_err)?,
138 Get::Last => self.inner.get_last().map_err(map_cursor_err)?,
139 Get::Next => {
140 if self.state == CursorState::NotInitialized {
141 self.inner.get_first().map_err(map_cursor_err)?
143 } else {
144 self.inner
145 .retrieve_next(GetMode::Next)
146 .map_err(map_cursor_err)?
147 }
148 }
149 Get::Prev => {
150 if self.state == CursorState::NotInitialized {
151 self.inner.get_last().map_err(map_cursor_err)?
153 } else {
154 self.inner
155 .retrieve_next(GetMode::Prev)
156 .map_err(map_cursor_err)?
157 }
158 }
159 Get::NextDup => {
160 self.check_initialized()?;
161 self.inner
162 .retrieve_next(GetMode::NextDup)
163 .map_err(map_cursor_err)?
164 }
165 Get::PrevDup => {
166 self.check_initialized()?;
167 self.inner
168 .retrieve_next(GetMode::PrevDup)
169 .map_err(map_cursor_err)?
170 }
171 Get::NextNoDup => {
172 if self.state == CursorState::NotInitialized {
173 self.inner.get_first().map_err(map_cursor_err)?
174 } else {
175 self.inner
176 .retrieve_next(GetMode::NextNoDup)
177 .map_err(map_cursor_err)?
178 }
179 }
180 Get::PrevNoDup => {
181 if self.state == CursorState::NotInitialized {
182 self.inner.get_last().map_err(map_cursor_err)?
183 } else {
184 self.inner
185 .retrieve_next(GetMode::PrevNoDup)
186 .map_err(map_cursor_err)?
187 }
188 }
189 Get::SearchBoth => {
190 let key_bytes = key.get_data().unwrap_or(&[]);
191 let data_bytes = data.get_data();
192 self.inner
193 .search(key_bytes, data_bytes, SearchMode::Both)
194 .map_err(map_cursor_err)?
195 }
196 Get::SearchBothRange => {
200 let key_bytes = key.get_data().unwrap_or(&[]);
201 let data_bytes = data.get_data();
202 self.inner
203 .search(key_bytes, data_bytes, SearchMode::BothRange)
204 .map_err(map_cursor_err)?
205 }
206 Get::Current => {
207 if self.inner.is_current_slot_deleted() {
212 return Ok(OperationStatus::NotFound);
213 }
214 let (k, v) =
215 self.inner.get_current().map_err(map_cursor_err)?;
216 data.set_data(&v);
217 key.set_data(&k);
218 self.state = CursorState::Initialized;
219 return Ok(OperationStatus::Success);
220 }
221 Get::SearchLte => {
231 return Err(NoxuError::Unsupported(
232 "Get::SearchLte".to_string(),
233 ));
234 }
235 Get::FirstDup => {
236 return Err(NoxuError::Unsupported(
237 "Get::FirstDup".to_string(),
238 ));
239 }
240 Get::LastDup => {
241 return Err(NoxuError::Unsupported("Get::LastDup".to_string()));
242 }
243 };
244
245 match status {
246 noxu_dbi::OperationStatus::Success => {
247 let (k, v) =
248 self.inner.get_current().map_err(map_cursor_err)?;
249 data.set_data(&v);
250 key.set_data(&k);
253 self.state = CursorState::Initialized;
254 Ok(OperationStatus::Success)
255 }
256 _ => {
257 if matches!(
258 get_type,
259 Get::First
260 | Get::Last
261 | Get::Search
262 | Get::SearchGte
263 | Get::SearchRange
264 | Get::SearchBoth
265 | Get::SearchBothRange
266 ) {
267 self.state = CursorState::NotInitialized;
268 }
269 Ok(OperationStatus::NotFound)
270 }
271 }
272 }
273
274 pub fn put(
303 &mut self,
304 key: &DatabaseEntry,
305 data: &DatabaseEntry,
306 put_type: Put,
307 ) -> Result<OperationStatus> {
308 self.check_open()?;
309
310 if self.read_only {
311 return Err(NoxuError::OperationNotAllowed(
312 "Cannot write with a read-only cursor".to_string(),
313 ));
314 }
315
316 let key_bytes = key.get_data().unwrap_or(&[]);
317 let data_bytes = data.get_data().unwrap_or(&[]);
318
319 let put_mode = match put_type {
320 Put::Overwrite => PutMode::Overwrite,
321 Put::NoOverwrite => PutMode::NoOverwrite,
322 Put::NoDupData => PutMode::NoDupData,
327 Put::Current => {
328 self.check_initialized()?;
329 PutMode::Current
330 }
331 };
332
333 match self
334 .inner
335 .put(key_bytes, data_bytes, put_mode)
336 .map_err(map_cursor_err)?
337 {
338 noxu_dbi::OperationStatus::KeyExist => {
339 Ok(OperationStatus::KeyExists)
340 }
341 _ => {
342 self.state = CursorState::Initialized;
343 Ok(OperationStatus::Success)
344 }
345 }
346 }
347
348 pub fn delete(&mut self) -> Result<OperationStatus> {
354 self.check_open()?;
355 self.check_initialized()?;
356
357 if self.read_only {
358 return Err(NoxuError::OperationNotAllowed(
359 "Cannot delete with a read-only cursor".to_string(),
360 ));
361 }
362
363 self.inner.delete().map_err(map_cursor_err)?;
364 self.state = CursorState::NotInitialized;
365 Ok(OperationStatus::Success)
366 }
367
368 pub fn count(&self) -> Result<u64> {
385 self.check_open()?;
386
387 if self.state != CursorState::Initialized {
388 return Ok(0);
389 }
390
391 let n = self.inner.count().map_err(map_cursor_err)?;
397 if n < 1 {
398 return Err(NoxuError::OperationNotAllowed(format!(
399 "cursor count() returned {n} while positioned (invariant violated)",
400 )));
401 }
402 Ok(n as u64)
403 }
404
405 pub fn close(&mut self) -> Result<()> {
421 if self.state == CursorState::Closed {
422 return Ok(());
423 }
424 self.state = CursorState::Closed;
425 self.inner.close().map_err(map_cursor_err)
429 }
430
431 pub fn is_valid(&self) -> bool {
433 self.state != CursorState::Closed
434 }
435
436 pub fn get_state(&self) -> CursorState {
438 self.state
439 }
440
441 pub fn is_read_only(&self) -> bool {
443 self.read_only
444 }
445
446 fn check_open(&self) -> Result<()> {
448 if self.state == CursorState::Closed {
449 Err(NoxuError::OperationNotAllowed(
450 "Cursor has been closed".to_string(),
451 ))
452 } else {
453 Ok(())
454 }
455 }
456
457 fn check_initialized(&self) -> Result<()> {
459 if self.state != CursorState::Initialized {
460 Err(NoxuError::OperationNotAllowed(
461 "Cursor is not positioned on a record".to_string(),
462 ))
463 } else {
464 Ok(())
465 }
466 }
467}
468
469impl Drop for Cursor {
470 fn drop(&mut self) {
471 if self.state == CursorState::Initialized {
477 log::warn!("Cursor dropped without close (still positioned)");
478 }
479 if self.state != CursorState::Closed {
483 let _ = self.inner.close();
484 self.state = CursorState::Closed;
485 }
486 }
487}
488
489#[cfg(test)]
490mod tests {
491 use super::*;
492 use noxu_dbi::{
493 DatabaseConfig as DbiDatabaseConfig, DatabaseId, DatabaseImpl, DbType,
494 };
495 use noxu_sync::RwLock;
496 use std::sync::Arc;
497
498 fn make_cursor(read_only: bool) -> Cursor {
500 let db_id = DatabaseId::new(1);
501 let config = DbiDatabaseConfig::default();
502 let db_impl =
503 DatabaseImpl::new(db_id, "test".to_string(), DbType::User, &config);
504 let db_arc = Arc::new(RwLock::new(db_impl));
505 let inner = CursorImpl::new(db_arc, 0);
506 Cursor::from_impl(inner, read_only)
507 }
508
509 fn make_cursor_with(records: Vec<(&[u8], &[u8])>) -> Cursor {
511 let db_id = DatabaseId::new(1);
512 let config = DbiDatabaseConfig::default();
513 let db_impl =
514 DatabaseImpl::new(db_id, "test".to_string(), DbType::User, &config);
515 let db_arc = Arc::new(RwLock::new(db_impl));
516
517 {
518 let mut tmp = CursorImpl::new(Arc::clone(&db_arc), 0);
519 for (k, v) in &records {
520 tmp.put(k, v, PutMode::Overwrite).unwrap();
521 }
522 }
523
524 let inner = CursorImpl::new(db_arc, 0);
525 Cursor::from_impl(inner, false)
526 }
527
528 #[test]
529 fn test_new_cursor() {
530 let cursor = make_cursor(false);
531 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
532 assert!(cursor.is_valid());
533 assert!(!cursor.is_read_only());
534 }
535
536 #[test]
537 fn test_read_only_cursor() {
538 let cursor = make_cursor(true);
539 assert!(cursor.is_read_only());
540 }
541
542 #[test]
543 fn test_search() {
544 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
545 let mut key = DatabaseEntry::from_bytes(b"key1");
546 let mut data = DatabaseEntry::new();
547
548 let status =
549 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
550 assert_eq!(status, OperationStatus::Success);
551 assert_eq!(data.get_data().unwrap(), b"value1");
552 assert_eq!(cursor.get_state(), CursorState::Initialized);
553 }
554
555 #[test]
556 fn test_search_not_found() {
557 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
558 let mut key = DatabaseEntry::from_bytes(b"key2");
559 let mut data = DatabaseEntry::new();
560
561 let status =
562 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
563 assert_eq!(status, OperationStatus::NotFound);
564 }
565
566 #[test]
567 fn test_first() {
568 let mut cursor = make_cursor_with(vec![
569 (b"key3", b"value3"),
570 (b"key1", b"value1"),
571 (b"key2", b"value2"),
572 ]);
573 let mut key = DatabaseEntry::new();
574 let mut data = DatabaseEntry::new();
575
576 let status = cursor.get(&mut key, &mut data, Get::First, None).unwrap();
577 assert_eq!(status, OperationStatus::Success);
578 assert_eq!(data.get_data().unwrap(), b"value1");
579 assert_eq!(cursor.get_state(), CursorState::Initialized);
580 }
581
582 #[test]
583 fn test_last() {
584 let mut cursor = make_cursor_with(vec![
585 (b"key3", b"value3"),
586 (b"key1", b"value1"),
587 (b"key2", b"value2"),
588 ]);
589 let mut key = DatabaseEntry::new();
590 let mut data = DatabaseEntry::new();
591
592 let status = cursor.get(&mut key, &mut data, Get::Last, None).unwrap();
593 assert_eq!(status, OperationStatus::Success);
594 assert_eq!(data.get_data().unwrap(), b"value3");
595 }
596
597 #[test]
598 fn test_next_iteration() {
599 let mut cursor = make_cursor_with(vec![
600 (b"key3", b"value3"),
601 (b"key1", b"value1"),
602 (b"key2", b"value2"),
603 ]);
604 let mut key = DatabaseEntry::new();
605 let mut data = DatabaseEntry::new();
606
607 let status = cursor.get(&mut key, &mut data, Get::First, None).unwrap();
608 assert_eq!(status, OperationStatus::Success);
609 assert_eq!(data.get_data().unwrap(), b"value1");
610
611 let status = cursor.get(&mut key, &mut data, Get::Next, None).unwrap();
612 assert_eq!(status, OperationStatus::Success);
613 assert_eq!(data.get_data().unwrap(), b"value2");
614
615 let status = cursor.get(&mut key, &mut data, Get::Next, None).unwrap();
616 assert_eq!(status, OperationStatus::Success);
617 assert_eq!(data.get_data().unwrap(), b"value3");
618
619 let status = cursor.get(&mut key, &mut data, Get::Next, None).unwrap();
620 assert_eq!(status, OperationStatus::NotFound);
621 }
622
623 #[test]
624 fn test_prev_iteration() {
625 let mut cursor = make_cursor_with(vec![
626 (b"key3", b"value3"),
627 (b"key1", b"value1"),
628 (b"key2", b"value2"),
629 ]);
630 let mut key = DatabaseEntry::new();
631 let mut data = DatabaseEntry::new();
632
633 let status = cursor.get(&mut key, &mut data, Get::Last, None).unwrap();
634 assert_eq!(status, OperationStatus::Success);
635 assert_eq!(data.get_data().unwrap(), b"value3");
636
637 let status = cursor.get(&mut key, &mut data, Get::Prev, None).unwrap();
638 assert_eq!(status, OperationStatus::Success);
639 assert_eq!(data.get_data().unwrap(), b"value2");
640
641 let status = cursor.get(&mut key, &mut data, Get::Prev, None).unwrap();
642 assert_eq!(status, OperationStatus::Success);
643 assert_eq!(data.get_data().unwrap(), b"value1");
644
645 let status = cursor.get(&mut key, &mut data, Get::Prev, None).unwrap();
646 assert_eq!(status, OperationStatus::NotFound);
647 }
648
649 #[test]
650 fn test_current() {
651 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
652 let mut key = DatabaseEntry::from_bytes(b"key1");
653 let mut data = DatabaseEntry::new();
654
655 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
656
657 let status =
658 cursor.get(&mut key, &mut data, Get::Current, None).unwrap();
659 assert_eq!(status, OperationStatus::Success);
660 assert_eq!(data.get_data().unwrap(), b"value1");
661 }
662
663 #[test]
664 fn test_current_not_initialized() {
665 let mut cursor = make_cursor(false);
666 let mut key = DatabaseEntry::new();
667 let mut data = DatabaseEntry::new();
668
669 let result = cursor.get(&mut key, &mut data, Get::Current, None);
670 assert!(result.is_err());
671 }
672
673 #[test]
674 fn test_put_overwrite() {
675 let mut cursor = make_cursor(false);
676
677 let mut key = DatabaseEntry::from_bytes(b"key1");
678 let data = DatabaseEntry::from_bytes(b"value1");
679
680 let status = cursor.put(&key, &data, Put::Overwrite).unwrap();
681 assert_eq!(status, OperationStatus::Success);
682 assert_eq!(cursor.get_state(), CursorState::Initialized);
683
684 let mut out = DatabaseEntry::new();
686 let s = cursor.get(&mut key, &mut out, Get::Search, None).unwrap();
687 assert_eq!(s, OperationStatus::Success);
688 assert_eq!(out.get_data().unwrap(), b"value1");
689 }
690
691 #[test]
692 fn test_put_no_overwrite() {
693 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
694
695 let key = DatabaseEntry::from_bytes(b"key1");
696 let data = DatabaseEntry::from_bytes(b"value2");
697
698 let status = cursor.put(&key, &data, Put::NoOverwrite).unwrap();
699 assert_eq!(status, OperationStatus::KeyExists);
700 }
701
702 #[test]
703 fn test_put_no_overwrite_new_key() {
704 let mut cursor = make_cursor(false);
705
706 let mut key = DatabaseEntry::from_bytes(b"key1");
707 let data = DatabaseEntry::from_bytes(b"value1");
708
709 let status = cursor.put(&key, &data, Put::NoOverwrite).unwrap();
710 assert_eq!(status, OperationStatus::Success);
711
712 let mut out = DatabaseEntry::new();
714 let s = cursor.get(&mut key, &mut out, Get::Search, None).unwrap();
715 assert_eq!(s, OperationStatus::Success);
716 assert_eq!(out.get_data().unwrap(), b"value1");
717 }
718
719 #[test]
720 fn test_put_current() {
721 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
722
723 let mut key = DatabaseEntry::from_bytes(b"key1");
724 let mut data = DatabaseEntry::new();
725 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
726
727 let new_data = DatabaseEntry::from_bytes(b"value2");
728 let status = cursor.put(&key, &new_data, Put::Current).unwrap();
729 assert_eq!(status, OperationStatus::Success);
730
731 let mut out = DatabaseEntry::new();
733 cursor.get(&mut key, &mut out, Get::Search, None).unwrap();
734 assert_eq!(out.get_data().unwrap(), b"value2");
735 }
736
737 #[test]
738 fn test_put_read_only() {
739 let mut cursor = make_cursor(true);
740
741 let key = DatabaseEntry::from_bytes(b"key1");
742 let data = DatabaseEntry::from_bytes(b"value1");
743
744 let result = cursor.put(&key, &data, Put::Overwrite);
745 assert!(result.is_err());
746 }
747
748 #[test]
749 fn test_delete() {
750 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
751
752 let mut key = DatabaseEntry::from_bytes(b"key1");
753 let mut data = DatabaseEntry::new();
754 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
755
756 let status = cursor.delete().unwrap();
757 assert_eq!(status, OperationStatus::Success);
758 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
759
760 let s = cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
762 assert_eq!(s, OperationStatus::NotFound);
763 }
764
765 #[test]
766 fn test_delete_not_positioned() {
767 let mut cursor = make_cursor(false);
768 let result = cursor.delete();
769 assert!(result.is_err());
770 }
771
772 #[test]
773 fn test_delete_read_only() {
774 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
775
776 let mut key = DatabaseEntry::from_bytes(b"key1");
777 let mut data = DatabaseEntry::new();
778 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
779
780 cursor.read_only = true;
782 let result = cursor.delete();
783 assert!(result.is_err());
784 }
785
786 #[test]
787 fn test_count() {
788 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
789
790 assert_eq!(cursor.count().unwrap(), 0);
792
793 let mut key = DatabaseEntry::from_bytes(b"key1");
795 let mut data = DatabaseEntry::new();
796 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
797
798 assert_eq!(cursor.count().unwrap(), 1);
800 }
801
802 #[test]
803 fn test_close() {
804 let mut cursor = make_cursor(false);
805
806 assert!(cursor.is_valid());
807 cursor.close().unwrap();
808 assert!(!cursor.is_valid());
809 assert_eq!(cursor.get_state(), CursorState::Closed);
810 }
811
812 #[test]
813 fn test_close_twice() {
814 let mut cursor = make_cursor(false);
816
817 cursor.close().unwrap();
818 cursor.close().expect("close() must be idempotent");
820 }
821
822 #[test]
823 fn test_close_propagates_to_inner() {
824 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
827
828 let mut key = DatabaseEntry::from_bytes(b"key1");
829 let mut data = DatabaseEntry::new();
830 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
831 cursor.close().unwrap();
833
834 let result = cursor.inner.get_first();
837 assert!(
838 result.is_err(),
839 "inner cursor must be closed after outer close()",
840 );
841 }
842
843 #[test]
844 fn test_operations_after_close() {
845 let mut cursor = make_cursor(false);
846
847 cursor.close().unwrap();
848
849 let mut key = DatabaseEntry::new();
850 let mut data = DatabaseEntry::new();
851
852 let result = cursor.get(&mut key, &mut data, Get::First, None);
853 assert!(result.is_err());
854 }
855
856 #[test]
857 fn test_empty_database_iteration() {
858 let mut cursor = make_cursor(false);
859
860 let mut key = DatabaseEntry::new();
861 let mut data = DatabaseEntry::new();
862
863 let status = cursor.get(&mut key, &mut data, Get::First, None).unwrap();
864 assert_eq!(status, OperationStatus::NotFound);
865 }
866
867 #[test]
868 fn test_sorted_iteration() {
869 let mut cursor = make_cursor_with(vec![
870 (b"zebra", b"z"),
871 (b"apple", b"a"),
872 (b"mango", b"m"),
873 ]);
874 let mut key = DatabaseEntry::new();
875 let mut data = DatabaseEntry::new();
876
877 let mut values = Vec::new();
878
879 let mut status =
880 cursor.get(&mut key, &mut data, Get::First, None).unwrap();
881 while status == OperationStatus::Success {
882 values.push(data.get_data().unwrap().to_vec());
883 status = cursor.get(&mut key, &mut data, Get::Next, None).unwrap();
884 }
885
886 assert_eq!(values, vec![b"a".to_vec(), b"m".to_vec(), b"z".to_vec()]);
887 }
888
889 #[test]
890 fn test_next_from_uninitialized() {
891 let mut cursor =
892 make_cursor_with(vec![(b"key1", b"value1"), (b"key2", b"value2")]);
893 let mut key = DatabaseEntry::new();
894 let mut data = DatabaseEntry::new();
895
896 let status = cursor.get(&mut key, &mut data, Get::Next, None).unwrap();
898 assert_eq!(status, OperationStatus::Success);
899 assert_eq!(data.get_data().unwrap(), b"value1");
900 }
901
902 #[test]
903 fn test_prev_from_uninitialized() {
904 let mut cursor =
905 make_cursor_with(vec![(b"key1", b"value1"), (b"key2", b"value2")]);
906 let mut key = DatabaseEntry::new();
907 let mut data = DatabaseEntry::new();
908
909 let status = cursor.get(&mut key, &mut data, Get::Prev, None).unwrap();
911 assert_eq!(status, OperationStatus::Success);
912 assert_eq!(data.get_data().unwrap(), b"value2");
913 }
914
915 #[test]
916 fn test_cursor_state_transitions() {
917 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
918 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
919
920 let mut key = DatabaseEntry::from_bytes(b"key1");
921 let mut data = DatabaseEntry::new();
922 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
923 assert_eq!(cursor.get_state(), CursorState::Initialized);
924
925 cursor.delete().unwrap();
926 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
927
928 cursor.close().unwrap();
929 assert_eq!(cursor.get_state(), CursorState::Closed);
930 }
931
932 #[test]
942 fn test_search_gte_empty_key_returns_not_found() {
943 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
944 let mut key = DatabaseEntry::new(); let mut data = DatabaseEntry::new();
946
947 let status =
948 cursor.get(&mut key, &mut data, Get::SearchGte, None).unwrap();
949 assert_eq!(status, OperationStatus::Success);
951 assert_eq!(data.get_data().unwrap(), b"value1");
952 }
953
954 #[test]
956 fn test_search_empty_key_returns_not_found() {
957 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
961 let mut key = DatabaseEntry::new(); let mut data = DatabaseEntry::new();
963
964 let status =
965 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
966 assert_eq!(status, OperationStatus::NotFound);
967 }
968
969 #[test]
974 fn test_get_other_variant_returns_not_found() {
975 let mut cursor = make_cursor_with(vec![(b"key1", b"value1")]);
976 let mut key = DatabaseEntry::from_bytes(b"key1");
977 let mut data = DatabaseEntry::new();
978
979 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
981
982 let status =
984 cursor.get(&mut key, &mut data, Get::NextDup, None).unwrap();
985 assert_eq!(status, OperationStatus::NotFound);
986 }
987
988 #[test]
994 fn test_put_no_dup_data_inserts_new_key() {
995 let mut cursor = make_cursor(false);
996
997 let mut key = DatabaseEntry::from_bytes(b"k");
998 let data = DatabaseEntry::from_bytes(b"v");
999
1000 let status = cursor.put(&key, &data, Put::NoDupData).unwrap();
1001 assert_eq!(status, OperationStatus::Success);
1002
1003 let mut out = DatabaseEntry::new();
1005 let s = cursor.get(&mut key, &mut out, Get::Search, None).unwrap();
1006 assert_eq!(s, OperationStatus::Success);
1007 assert_eq!(out.get_data().unwrap(), b"v");
1008 }
1009
1010 #[test]
1012 fn test_put_no_dup_data_key_exists() {
1013 let mut cursor = make_cursor_with(vec![(b"k", b"v")]);
1014
1015 let key = DatabaseEntry::from_bytes(b"k");
1016 let data = DatabaseEntry::from_bytes(b"v2");
1017
1018 let status = cursor.put(&key, &data, Put::NoDupData).unwrap();
1019 assert_eq!(status, OperationStatus::KeyExists);
1020 }
1021
1022 #[test]
1024 fn test_put_current_not_initialized_returns_error() {
1025 let mut cursor = make_cursor(false);
1026
1027 let key = DatabaseEntry::from_bytes(b"k");
1028 let data = DatabaseEntry::from_bytes(b"v");
1029
1030 let result = cursor.put(&key, &data, Put::Current);
1031 assert!(result.is_err());
1032 }
1033
1034 #[test]
1036 fn test_first_not_found_resets_state() {
1037 let mut cursor = make_cursor(false); let mut key = DatabaseEntry::new();
1039 let mut data = DatabaseEntry::new();
1040
1041 let status = cursor.get(&mut key, &mut data, Get::First, None).unwrap();
1042 assert_eq!(status, OperationStatus::NotFound);
1043 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
1045 }
1046
1047 #[test]
1049 fn test_last_not_found_resets_state() {
1050 let mut cursor = make_cursor(false); let mut key = DatabaseEntry::new();
1052 let mut data = DatabaseEntry::new();
1053
1054 let status = cursor.get(&mut key, &mut data, Get::Last, None).unwrap();
1055 assert_eq!(status, OperationStatus::NotFound);
1056 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
1057 }
1058
1059 #[test]
1061 fn test_search_not_found_resets_state() {
1062 let mut cursor = make_cursor_with(vec![(b"key1", b"v1")]);
1063 let mut key = DatabaseEntry::from_bytes(b"key1");
1064 let mut data = DatabaseEntry::new();
1065
1066 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
1068 assert_eq!(cursor.get_state(), CursorState::Initialized);
1069
1070 let mut key_miss = DatabaseEntry::from_bytes(b"missing");
1072 let status =
1073 cursor.get(&mut key_miss, &mut data, Get::Search, None).unwrap();
1074 assert_eq!(status, OperationStatus::NotFound);
1075 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
1076 }
1077
1078 #[test]
1080 fn test_search_gte_not_found_resets_state() {
1081 let mut cursor = make_cursor_with(vec![(b"key1", b"v1")]);
1082 let mut key = DatabaseEntry::from_bytes(b"key1");
1083 let mut data = DatabaseEntry::new();
1084
1085 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
1086
1087 let mut key_big = DatabaseEntry::from_bytes(b"zzz");
1088 let status =
1089 cursor.get(&mut key_big, &mut data, Get::SearchGte, None).unwrap();
1090 assert_eq!(status, OperationStatus::NotFound);
1091 assert_eq!(cursor.get_state(), CursorState::NotInitialized);
1092 }
1093
1094 #[test]
1096 fn test_count_on_closed_cursor_returns_error() {
1097 let mut cursor = make_cursor(false);
1098 cursor.close().unwrap();
1099 let result = cursor.count();
1100 assert!(result.is_err());
1101 }
1102
1103 #[test]
1106 fn test_delete_not_positioned_check_fires_before_read_only_check() {
1107 let mut cursor = make_cursor(true); let result = cursor.delete();
1109 assert!(result.is_err());
1111 }
1112
1113 #[test]
1116 fn test_search_gte_positions_at_ge_key() {
1117 let mut cursor = make_cursor_with(vec![(b"mango", b"yellow")]);
1118 let mut key = DatabaseEntry::from_bytes(b"apple"); let mut data = DatabaseEntry::new();
1120
1121 let status =
1122 cursor.get(&mut key, &mut data, Get::SearchGte, None).unwrap();
1123 assert_eq!(status, OperationStatus::Success);
1124 assert_eq!(data.get_data().unwrap(), b"yellow");
1125 assert_eq!(cursor.get_state(), CursorState::Initialized);
1126 }
1127
1128 fn make_inner_closed_cursor() -> Cursor {
1138 let mut c = make_cursor(false);
1139 c.inner.close().unwrap(); c
1142 }
1143
1144 fn make_inner_closed_cursor_initialized() -> Cursor {
1147 let mut c = make_cursor(false);
1148 c.state = CursorState::Initialized;
1150 c.inner.close().unwrap();
1151 c
1152 }
1153
1154 #[test]
1157 fn test_search_map_err_closure_covered() {
1158 let mut cursor = make_inner_closed_cursor();
1159 let mut key = DatabaseEntry::from_bytes(b"k");
1160 let mut data = DatabaseEntry::new();
1161 let result = cursor.get(&mut key, &mut data, Get::Search, None);
1162 assert!(result.is_err());
1163 }
1164
1165 #[test]
1167 fn test_search_gte_map_err_closure_covered() {
1168 let mut cursor = make_inner_closed_cursor();
1169 let mut key = DatabaseEntry::from_bytes(b"k");
1170 let mut data = DatabaseEntry::new();
1171 let result = cursor.get(&mut key, &mut data, Get::SearchGte, None);
1172 assert!(result.is_err());
1173 }
1174
1175 #[test]
1177 fn test_first_map_err_closure_covered() {
1178 let mut cursor = make_inner_closed_cursor();
1179 let mut key = DatabaseEntry::new();
1180 let mut data = DatabaseEntry::new();
1181 let result = cursor.get(&mut key, &mut data, Get::First, None);
1182 assert!(result.is_err());
1183 }
1184
1185 #[test]
1187 fn test_last_map_err_closure_covered() {
1188 let mut cursor = make_inner_closed_cursor();
1189 let mut key = DatabaseEntry::new();
1190 let mut data = DatabaseEntry::new();
1191 let result = cursor.get(&mut key, &mut data, Get::Last, None);
1192 assert!(result.is_err());
1193 }
1194
1195 #[test]
1197 fn test_next_uninit_map_err_closure_covered() {
1198 let mut cursor = make_inner_closed_cursor();
1199 let mut key = DatabaseEntry::new();
1200 let mut data = DatabaseEntry::new();
1201 let result = cursor.get(&mut key, &mut data, Get::Next, None);
1203 assert!(result.is_err());
1204 }
1205
1206 #[test]
1208 fn test_next_init_map_err_closure_covered() {
1209 let mut cursor = make_inner_closed_cursor_initialized();
1210 let mut key = DatabaseEntry::new();
1211 let mut data = DatabaseEntry::new();
1212 let result = cursor.get(&mut key, &mut data, Get::Next, None);
1214 assert!(result.is_err());
1215 }
1216
1217 #[test]
1219 fn test_prev_uninit_map_err_closure_covered() {
1220 let mut cursor = make_inner_closed_cursor();
1221 let mut key = DatabaseEntry::new();
1222 let mut data = DatabaseEntry::new();
1223 let result = cursor.get(&mut key, &mut data, Get::Prev, None);
1224 assert!(result.is_err());
1225 }
1226
1227 #[test]
1229 fn test_prev_init_map_err_closure_covered() {
1230 let mut cursor = make_inner_closed_cursor_initialized();
1231 let mut key = DatabaseEntry::new();
1232 let mut data = DatabaseEntry::new();
1233 let result = cursor.get(&mut key, &mut data, Get::Prev, None);
1234 assert!(result.is_err());
1235 }
1236
1237 #[test]
1239 fn test_current_map_err_closure_covered() {
1240 let mut cursor = make_inner_closed_cursor_initialized();
1241 let mut key = DatabaseEntry::new();
1242 let mut data = DatabaseEntry::new();
1243 let result = cursor.get(&mut key, &mut data, Get::Current, None);
1246 assert!(result.is_err());
1247 }
1248
1249 #[test]
1256 fn test_get_success_branch_get_current_map_err() {
1257 let mut cursor = make_cursor_with(vec![(b"key1", b"val1")]);
1258 let mut key = DatabaseEntry::from_bytes(b"key1");
1260 let mut data = DatabaseEntry::new();
1261 cursor.get(&mut key, &mut data, Get::Search, None).unwrap();
1262 cursor.inner.close().unwrap();
1264 let mut key2 = DatabaseEntry::new();
1266 let mut data2 = DatabaseEntry::new();
1267 let result = cursor.get(&mut key2, &mut data2, Get::First, None);
1268 assert!(result.is_err());
1269 }
1270
1271 #[test]
1273 fn test_put_map_err_closure_covered() {
1274 let mut cursor = make_inner_closed_cursor();
1275 let key = DatabaseEntry::from_bytes(b"k");
1276 let data = DatabaseEntry::from_bytes(b"v");
1277 let result = cursor.put(&key, &data, Put::Overwrite);
1278 assert!(result.is_err());
1279 }
1280
1281 #[test]
1284 fn test_search_both_range_on_dup_db() {
1285 use noxu_dbi::{
1286 DatabaseConfig as DbiCfg, DatabaseId, DatabaseImpl, DbType,
1287 };
1288 use noxu_sync::RwLock;
1289 use std::sync::Arc;
1290
1291 let db_id = DatabaseId::new(7);
1292 let config = DbiCfg { sorted_duplicates: true, ..DbiCfg::default() };
1293 let db_impl = DatabaseImpl::new(
1294 db_id,
1295 "dup_test".to_string(),
1296 DbType::User,
1297 &config,
1298 );
1299 let db_arc = Arc::new(RwLock::new(db_impl));
1300
1301 {
1303 let mut tmp = CursorImpl::new(Arc::clone(&db_arc), 0);
1304 tmp.put(b"k", b"a", PutMode::Overwrite).unwrap();
1305 tmp.put(b"k", b"b", PutMode::Overwrite).unwrap();
1306 tmp.put(b"k", b"d", PutMode::Overwrite).unwrap();
1307 }
1308
1309 let inner = CursorImpl::new(db_arc, 0);
1310 let mut cursor = Cursor::from_impl(inner, false);
1311
1312 let mut k = DatabaseEntry::from_bytes(b"k");
1315 let mut d = DatabaseEntry::from_bytes(b"c");
1316 let s = cursor.get(&mut k, &mut d, Get::SearchBothRange, None).unwrap();
1317 assert_eq!(s, OperationStatus::Success);
1318 assert_eq!(d.get_data().unwrap(), b"d");
1319 }
1320
1321 #[test]
1323 fn test_delete_map_err_closure_covered() {
1324 let mut cursor = make_inner_closed_cursor_initialized();
1325 let result = cursor.delete();
1326 assert!(result.is_err());
1327 }
1328}