Skip to main content

noxu_dbi/
database_config.rs

1//! Database configuration.
2//!
3
4use std::sync::Arc;
5
6use noxu_tree::KeyComparatorFn;
7
8use crate::trigger::Trigger;
9
10/// A persisted-identity + comparison-function pair threaded from the public
11/// `noxu_db::Comparator` down to `DatabaseImpl`.
12///
13/// The `identity` is the stable string persisted in the database record (the
14/// NameLN data) and re-checked at open; the `func` is the actual comparison
15/// closure threaded into the `Tree`.  JE `DatabaseImpl.btreeComparator` plus
16/// the persisted `btreeComparatorBytes` (the serialized class name).
17#[derive(Clone)]
18pub struct ConfigComparator {
19    /// Stable identity persisted in the database record.
20    pub identity: String,
21    /// The comparison closure threaded into the tree.
22    pub func: KeyComparatorFn,
23}
24
25impl std::fmt::Debug for ConfigComparator {
26    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27        f.debug_struct("ConfigComparator")
28            .field("identity", &self.identity)
29            .finish()
30    }
31}
32
33/// Configuration for a database.
34///
35///
36#[derive(Clone)]
37pub struct DatabaseConfig {
38    /// Allow database creation if it doesn't exist.
39    pub allow_create: bool,
40    /// Enable sorted duplicates.
41    pub sorted_duplicates: bool,
42    /// Enable key prefixing compression.
43    pub key_prefixing: bool,
44    /// Database is temporary (not persisted).
45    pub temporary: bool,
46    /// Database operations are transactional.
47    pub transactional: bool,
48    /// Database is read-only.
49    pub read_only: bool,
50    /// Whether this database participates in replication. Default `true`.
51    /// Only takes effect when the owning environment is itself replicated
52    /// (`EnvironmentImpl::is_replicated()`); on a plain (non-replicated)
53    /// environment every database is non-replicated regardless of this
54    /// value, since the environment itself is never marked replicated
55    /// there.
56    pub replicated: bool,
57    /// Maximum entries per node.
58    pub node_max_entries: i32,
59    /// Deferred write: skip WAL logging; flush only at eviction/checkpoint.
60    ///
61    ///
62    pub deferred_write: bool,
63    /// User-supplied B-tree key comparator (DBI-14).
64    ///
65    /// JE `DatabaseImpl.btreeComparator`.  `None` = unsigned-byte order.
66    pub btree_comparator: Option<ConfigComparator>,
67    /// User-supplied duplicate-data comparator (DBI-14).
68    ///
69    /// JE `DatabaseImpl.duplicateComparator`.
70    pub duplicate_comparator: Option<ConfigComparator>,
71    /// JE `DatabaseConfig.overrideBtreeComparator`: replace a persisted
72    /// comparator instead of rejecting a mismatch.
73    pub override_btree_comparator: bool,
74    /// JE `DatabaseConfig.overrideDuplicateComparator`.
75    pub override_duplicate_comparator: bool,
76    /// User-supplied database / transaction triggers, fired in registration
77    /// order (DB-TRIG).
78    ///
79    /// JE `DatabaseConfig.setTriggers` / `getTriggers` (a `List<Trigger>`).
80    /// Runtime-registered only: not persisted, not replicated — see
81    /// [`crate::trigger`].
82    pub triggers: Vec<Arc<dyn Trigger>>,
83}
84
85impl std::fmt::Debug for DatabaseConfig {
86    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87        f.debug_struct("DatabaseConfig")
88            .field("allow_create", &self.allow_create)
89            .field("sorted_duplicates", &self.sorted_duplicates)
90            .field("key_prefixing", &self.key_prefixing)
91            .field("temporary", &self.temporary)
92            .field("transactional", &self.transactional)
93            .field("read_only", &self.read_only)
94            .field("node_max_entries", &self.node_max_entries)
95            .field("deferred_write", &self.deferred_write)
96            .field("btree_comparator", &self.btree_comparator)
97            .field("duplicate_comparator", &self.duplicate_comparator)
98            .field("override_btree_comparator", &self.override_btree_comparator)
99            .field(
100                "override_duplicate_comparator",
101                &self.override_duplicate_comparator,
102            )
103            .field("triggers", &self.triggers.len())
104            .finish()
105    }
106}
107
108impl Default for DatabaseConfig {
109    fn default() -> Self {
110        DatabaseConfig {
111            allow_create: false,
112            sorted_duplicates: false,
113            key_prefixing: false,
114            temporary: false,
115            transactional: false,
116            read_only: false,
117            replicated: true,
118            node_max_entries: 128,
119            deferred_write: false,
120            btree_comparator: None,
121            duplicate_comparator: None,
122            override_btree_comparator: false,
123            override_duplicate_comparator: false,
124            triggers: Vec::new(),
125        }
126    }
127}
128
129impl DatabaseConfig {
130    /// Creates a new DatabaseConfig with default values.
131    pub fn new() -> Self {
132        Self::default()
133    }
134
135    /// Sets the allow_create flag.
136    pub fn set_allow_create(&mut self, allow_create: bool) -> &mut Self {
137        self.allow_create = allow_create;
138        self
139    }
140
141    /// Sets the sorted_duplicates flag.
142    pub fn set_sorted_duplicates(
143        &mut self,
144        sorted_duplicates: bool,
145    ) -> &mut Self {
146        self.sorted_duplicates = sorted_duplicates;
147        self
148    }
149
150    /// Sets the key_prefixing flag.
151    pub fn set_key_prefixing(&mut self, key_prefixing: bool) -> &mut Self {
152        self.key_prefixing = key_prefixing;
153        self
154    }
155
156    /// Sets the temporary flag.
157    pub fn set_temporary(&mut self, temporary: bool) -> &mut Self {
158        self.temporary = temporary;
159        self
160    }
161
162    /// Sets the transactional flag.
163    pub fn set_transactional(&mut self, transactional: bool) -> &mut Self {
164        self.transactional = transactional;
165        self
166    }
167
168    /// Sets the read_only flag.
169    pub fn set_read_only(&mut self, read_only: bool) -> &mut Self {
170        self.read_only = read_only;
171        self
172    }
173
174    /// Sets the replicated flag.
175    pub fn set_replicated(&mut self, replicated: bool) -> &mut Self {
176        self.replicated = replicated;
177        self
178    }
179
180    /// Sets the maximum entries per node.
181    pub fn set_node_max_entries(&mut self, max: i32) -> &mut Self {
182        self.node_max_entries = max;
183        self
184    }
185
186    /// Appends a trigger to the registration list (DB-TRIG).
187    ///
188    /// Triggers fire in the order they are added.  JE
189    /// `DatabaseConfig.setTriggers` (Noxu allows incremental registration).
190    pub fn add_trigger(&mut self, trigger: Arc<dyn Trigger>) -> &mut Self {
191        self.triggers.push(trigger);
192        self
193    }
194}
195
196#[cfg(test)]
197mod tests {
198    use super::*;
199
200    #[test]
201    fn test_default() {
202        let config = DatabaseConfig::default();
203        assert!(!config.allow_create);
204        assert!(!config.sorted_duplicates);
205        assert!(!config.key_prefixing);
206        assert!(!config.temporary);
207        assert!(!config.transactional);
208        assert!(!config.read_only);
209        assert_eq!(config.node_max_entries, 128);
210    }
211
212    #[test]
213    fn test_new() {
214        let config = DatabaseConfig::new();
215        assert!(!config.allow_create);
216    }
217
218    #[test]
219    fn test_setters() {
220        let mut config = DatabaseConfig::new();
221
222        config.set_allow_create(true);
223        assert!(config.allow_create);
224
225        config.set_sorted_duplicates(true);
226        assert!(config.sorted_duplicates);
227
228        config.set_key_prefixing(true);
229        assert!(config.key_prefixing);
230
231        config.set_temporary(true);
232        assert!(config.temporary);
233
234        config.set_transactional(true);
235        assert!(config.transactional);
236
237        config.set_read_only(true);
238        assert!(config.read_only);
239
240        config.set_node_max_entries(256);
241        assert_eq!(config.node_max_entries, 256);
242    }
243
244    #[test]
245    fn test_builder_pattern() {
246        let config = DatabaseConfig::new()
247            .set_allow_create(true)
248            .set_transactional(true)
249            .set_node_max_entries(512)
250            .clone();
251
252        assert!(config.allow_create);
253        assert!(config.transactional);
254        assert_eq!(config.node_max_entries, 512);
255    }
256}