Skip to main content

noxu_db/
cursor_config.rs

1//! Cursor configuration.
2//!
3
4/// Configuration for opening a cursor.
5///
6/// Specifies the configuration parameters used to open a cursor on a database.
7///
8/// # Changes in v1.5.1
9///
10/// Four fields that used to live on this struct (`read_committed`,
11/// `non_sticky`, `evict_ln`, `prefix_constraint`) were removed because
12/// the engine never consulted them.  See
13/// `docs/src/internal/v1.5-decisions-2026-05.md` for the full rationale
14/// and migration notes.
15///
16/// * `read_committed` — to use read-committed isolation, set it on the
17///   surrounding [`crate::transaction_config::TransactionConfig`] (it
18///   is honoured by [`crate::cursor::Cursor`] via the txn's locker)
19///   or pass [`crate::lock_mode::LockMode::ReadCommitted`] to a
20///   per-operation [`crate::read_options::ReadOptions`].
21/// * `non_sticky` — Rust cursors are bound to their owning scope and
22///   are not sticky to a transaction in the JE sense; the flag had
23///   no observable effect.
24/// * `evict_ln` — use [`crate::cache_mode::CacheMode::Unchanged`] /
25///   `EvictLn` on the surrounding `DatabaseConfig` instead.
26/// * `prefix_constraint` — application code should compare the
27///   returned key against its own prefix and stop iterating; the
28///   engine's BIN-level prefix is independent of the user's
29///   range-scan termination condition.
30#[derive(Debug, Clone, PartialEq, Eq, Default)]
31pub struct CursorConfig {
32    /// Use read-uncommitted isolation (dirty reads).
33    ///
34    /// When `true`, the cursor is opened in read-only mode and skips
35    /// read-lock acquisition.  This mirrors JE's
36    /// `CursorConfig.setReadUncommitted(true)` shape and is the only
37    /// isolation override consulted at cursor-open time.  Per-operation
38    /// `LockMode` overrides (passed via
39    /// [`crate::read_options::ReadOptions`]) take precedence at the
40    /// individual `get` call.
41    pub read_uncommitted: bool,
42}
43
44impl CursorConfig {
45    /// Creates a new CursorConfig with default settings.
46    pub fn new() -> Self {
47        Self::default()
48    }
49
50    /// Sets read-uncommitted isolation.
51    pub fn set_read_uncommitted(
52        &mut self,
53        read_uncommitted: bool,
54    ) -> &mut Self {
55        self.read_uncommitted = read_uncommitted;
56        self
57    }
58
59    /// Builder-style method to set read_uncommitted.
60    pub fn with_read_uncommitted(mut self, read_uncommitted: bool) -> Self {
61        self.read_uncommitted = read_uncommitted;
62        self
63    }
64
65    /// Creates a CursorConfig for read-uncommitted isolation.
66    pub fn read_uncommitted() -> Self {
67        Self::new().with_read_uncommitted(true)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_new_defaults_to_no_read_uncommitted() {
77        let config = CursorConfig::new();
78        assert!(!config.read_uncommitted);
79    }
80
81    #[test]
82    fn test_set_read_uncommitted() {
83        let mut config = CursorConfig::new();
84        config.set_read_uncommitted(true);
85        assert!(config.read_uncommitted);
86    }
87
88    #[test]
89    fn test_with_read_uncommitted() {
90        let config = CursorConfig::new().with_read_uncommitted(true);
91        assert!(config.read_uncommitted);
92    }
93
94    #[test]
95    fn test_read_uncommitted_factory() {
96        let config = CursorConfig::read_uncommitted();
97        assert!(config.read_uncommitted);
98    }
99
100    #[test]
101    fn test_default() {
102        let config = CursorConfig::default();
103        assert!(!config.read_uncommitted);
104    }
105
106    #[test]
107    fn test_clone_eq() {
108        let a = CursorConfig::read_uncommitted();
109        let b = a.clone();
110        assert_eq!(a, b);
111
112        let c = CursorConfig::new();
113        assert_ne!(a, c);
114    }
115
116    #[test]
117    fn test_debug_format_mentions_field() {
118        let config = CursorConfig::read_uncommitted();
119        let debug = format!("{:?}", config);
120        assert!(debug.contains("read_uncommitted"));
121    }
122}