1use crate::types::Value;
7use std::cmp::Ordering;
8
9pub const MAX_KEYS: usize = 64;
10
11#[derive(Debug, Clone)]
12struct Node {
13 leaf: bool,
14 keys: Vec<Value>, values: Vec<u64>, children: Vec<usize>, next: Option<usize>, }
19
20impl Node {
21 fn new(leaf: bool) -> Node {
22 Node {
23 leaf,
24 keys: Vec::new(),
25 values: Vec::new(),
26 children: Vec::new(),
27 next: None,
28 }
29 }
30}
31
32fn cmp_entry(k: &Value, id: u64, key: &Value, key_id: u64) -> Ordering {
33 match k.cmp_value(key) {
34 Ordering::Equal => id.cmp(&key_id),
35 other => other,
36 }
37}
38
39#[derive(Debug, Clone)]
40pub struct BTree {
41 nodes: Vec<Node>,
42 root: usize,
43 pub size: usize,
44}
45
46impl Default for BTree {
47 fn default() -> Self {
48 let nodes = vec![Node::new(true)];
49 BTree {
50 nodes,
51 root: 0,
52 size: 0,
53 }
54 }
55}
56
57impl BTree {
58 fn new_node(&mut self, leaf: bool) -> usize {
59 let id = self.nodes.len();
60 self.nodes.push(Node::new(leaf));
61 id
62 }
63
64 pub fn is_empty(&self) -> bool {
65 self.size == 0
66 }
67
68 fn find_first_leaf(&self, value: &Value) -> usize {
73 let mut node = self.root;
74 while !self.nodes[node].leaf {
75 let n = &self.nodes[node];
76 let idx = n
77 .keys
78 .iter()
79 .position(|k| k.cmp_value(value) != Ordering::Less)
80 .unwrap_or(n.keys.len());
81 node = n.children[idx];
82 }
83 node
84 }
85
86 fn leftmost_leaf(&self) -> usize {
87 let mut node = self.root;
88 while !self.nodes[node].leaf {
89 node = self.nodes[node].children[0];
90 }
91 node
92 }
93
94 fn find_entry_leaf(&self, value: &Value, row_id: u64) -> Option<usize> {
95 let mut leaf = self.find_first_leaf(value);
96 loop {
97 let node = &self.nodes[leaf];
98 for (key, id) in node.keys.iter().zip(&node.values) {
99 match cmp_entry(key, *id, value, row_id) {
100 Ordering::Less => {}
101 Ordering::Equal => return Some(leaf),
102 Ordering::Greater => return None,
103 }
104 }
105 leaf = node.next?;
106 }
107 }
108
109 fn insertion_leaf(&self, value: &Value, row_id: u64) -> usize {
113 let mut leaf = self.find_first_leaf(value);
114 loop {
115 let node = &self.nodes[leaf];
116 if node
117 .keys
118 .iter()
119 .zip(&node.values)
120 .any(|(key, id)| cmp_entry(key, *id, value, row_id) != Ordering::Less)
121 {
122 return leaf;
123 }
124 match node.next {
125 Some(next) => leaf = next,
126 None => return leaf,
127 }
128 }
129 }
130
131 fn path_to_leaf(&self, node: usize, target: usize, path: &mut Vec<usize>) -> bool {
132 path.push(node);
133 if node == target {
134 return self.nodes[node].leaf;
135 }
136 if self.nodes[node].leaf {
137 path.pop();
138 return false;
139 }
140 for child in self.nodes[node].children.iter().copied() {
141 if self.path_to_leaf(child, target, path) {
142 return true;
143 }
144 }
145 path.pop();
146 false
147 }
148
149 fn leaf_pos(&self, leaf: usize, value: &Value, row_id: u64) -> Option<usize> {
150 let n = &self.nodes[leaf];
151 let mut lo = 0usize;
152 let mut hi = n.keys.len();
153 while lo < hi {
154 let mid = (lo + hi) / 2;
155 match cmp_entry(&n.keys[mid], n.values[mid], value, row_id) {
156 Ordering::Less => lo = mid + 1,
157 Ordering::Greater => hi = mid,
158 Ordering::Equal => return Some(mid),
159 }
160 }
161 None
162 }
163
164 pub fn contains(&self, value: &Value, row_id: u64) -> bool {
165 if self.is_empty() {
166 return false;
167 }
168 self.find_entry_leaf(value, row_id).is_some()
169 }
170
171 pub fn lookup_eq(&self, value: &Value) -> Vec<u64> {
173 let mut out = Vec::new();
174 if self.is_empty() {
175 return out;
176 }
177 let mut node = self.find_first_leaf(value);
178 loop {
179 let n = &self.nodes[node];
180 for (k, v) in n.keys.iter().zip(n.values.iter()) {
181 match k.cmp_value(value) {
182 Ordering::Greater => return out,
183 Ordering::Equal => out.push(*v),
184 Ordering::Less => {}
185 }
186 }
187 match n.next {
188 Some(next) => node = next,
189 None => return out,
190 }
191 }
192 }
193
194 pub fn range_scan(&self, low: &Value, high: &Value) -> Vec<u64> {
196 let mut out = Vec::new();
197 if self.is_empty() {
198 return out;
199 }
200 if low.cmp_value(high) == Ordering::Greater {
201 return out;
202 }
203 let mut node = self.find_first_leaf(low);
204 loop {
205 let n = &self.nodes[node];
206 for (k, v) in n.keys.iter().zip(n.values.iter()) {
207 if k.cmp_value(high) == Ordering::Greater {
208 return out;
209 }
210 if k.cmp_value(low) != Ordering::Less {
211 out.push(*v);
212 }
213 }
214 match n.next {
215 Some(next) => node = next,
216 None => return out,
217 }
218 }
219 }
220
221 pub fn scan_all(&self) -> Vec<(Value, u64)> {
223 let mut out = Vec::new();
224 if self.is_empty() {
225 return out;
226 }
227 let mut node = self.leftmost_leaf();
228 loop {
229 let n = &self.nodes[node];
230 for i in 0..n.keys.len() {
231 out.push((n.keys[i].clone(), n.values[i]));
232 }
233 match n.next {
234 Some(next) => node = next,
235 None => return out,
236 }
237 }
238 }
239
240 pub fn insert(&mut self, value: Value, row_id: u64) {
241 if self.contains(&value, row_id) {
242 return;
243 }
244 let target = self.insertion_leaf(&value, row_id);
245 let mut path = Vec::new();
246 assert!(self.path_to_leaf(self.root, target, &mut path));
247 let split = self.insert_rec_at(&path, 0, value, row_id);
248 self.size += 1;
249 if let Some((median, right)) = split {
250 let left = self.root;
251 let new_root = self.new_node(false);
252 self.nodes[new_root].keys.push(median);
253 self.nodes[new_root].children.push(left);
254 self.nodes[new_root].children.push(right);
255 self.root = new_root;
256 }
257 }
258
259 fn insert_rec_at(
260 &mut self,
261 path: &[usize],
262 depth: usize,
263 value: Value,
264 row_id: u64,
265 ) -> Option<(Value, usize)> {
266 let node = path[depth];
267 if self.nodes[node].leaf {
268 let pos = self.nodes[node]
269 .keys
270 .iter()
271 .zip(&self.nodes[node].values)
272 .position(|(key, id)| cmp_entry(key, *id, &value, row_id) == Ordering::Greater)
273 .unwrap_or(self.nodes[node].keys.len());
274 self.nodes[node].keys.insert(pos, value);
275 self.nodes[node].values.insert(pos, row_id);
276 if self.nodes[node].keys.len() > MAX_KEYS {
277 Some(self.split_node(node))
278 } else {
279 None
280 }
281 } else {
282 let child = path[depth + 1];
283 let child_index = self.nodes[node]
284 .children
285 .iter()
286 .position(|candidate| *candidate == child)
287 .expect("path child belongs to parent");
288 if let Some((median, right)) = self.insert_rec_at(path, depth + 1, value, row_id) {
289 let n = &mut self.nodes[node];
290 n.keys.insert(child_index, median);
291 n.children.insert(child_index + 1, right);
292 if n.keys.len() > MAX_KEYS {
293 Some(self.split_node(node))
294 } else {
295 None
296 }
297 } else {
298 None
299 }
300 }
301 }
302
303 fn split_node(&mut self, node: usize) -> (Value, usize) {
304 let mid = MAX_KEYS / 2;
305 let right = self.new_node(self.nodes[node].leaf);
306 if self.nodes[node].leaf {
307 let median = self.nodes[node].keys[mid].clone();
308 self.nodes[right].keys = self.nodes[node].keys.split_off(mid);
309 self.nodes[right].values = self.nodes[node].values.split_off(mid);
310 self.nodes[right].next = self.nodes[node].next;
311 self.nodes[node].next = Some(right);
312 (median, right)
313 } else {
314 let mut keys_right = self.nodes[node].keys.split_off(mid);
315 let sep = keys_right.remove(0);
316 self.nodes[right].keys = keys_right;
317 self.nodes[right].children = self.nodes[node].children.split_off(mid + 1);
318 (sep, right)
319 }
320 }
321
322 pub fn delete(&mut self, value: &Value, row_id: u64) -> bool {
327 if self.is_empty() {
328 return false;
329 }
330 let Some(leaf) = self.find_entry_leaf(value, row_id) else {
331 return false;
332 };
333 let pos = self
334 .leaf_pos(leaf, value, row_id)
335 .expect("located entry exists");
336 self.nodes[leaf].keys.remove(pos);
337 self.nodes[leaf].values.remove(pos);
338 self.size = self.size.saturating_sub(1);
339 if self.size == 0 {
340 *self = Self::default();
341 }
342 true
343 }
344}
345
346#[cfg(test)]
347mod tests {
348 use super::*;
349
350 fn v(n: i64) -> Value {
351 Value::Integer(n)
352 }
353
354 #[test]
355 fn insert_and_lookup() {
356 let mut t = BTree::default();
357 for i in 0..1000 {
358 t.insert(v(i), i as u64);
359 }
360 assert_eq!(t.size, 1000);
361 for i in (0..1000).rev() {
362 assert!(t.contains(&v(i), i as u64));
363 assert_eq!(t.lookup_eq(&v(i)), vec![i as u64]);
364 }
365 }
366
367 #[test]
368 fn range_scan_order() {
369 let mut t = BTree::default();
370 for i in 0..5000 {
371 t.insert(v((i * 7919) % 5000), i as u64); }
373 let res = t.range_scan(&v(100), &v(200));
374 assert_eq!(res.len(), 101);
375 }
377
378 #[test]
379 fn duplicates_by_row_id() {
380 let mut t = BTree::default();
381 t.insert(v(5), 1);
382 t.insert(v(5), 2);
383 t.insert(v(5), 3);
384 assert_eq!(t.lookup_eq(&v(5)), vec![1, 2, 3]);
385 assert_eq!(t.size, 3);
386 t.delete(&v(5), 2);
387 assert_eq!(t.lookup_eq(&v(5)), vec![1, 3]);
388 assert_eq!(t.size, 2);
389 }
390
391 #[test]
392 fn duplicate_keys_survive_leaf_splits_and_out_of_order_ids() {
393 let mut t = BTree::default();
394 for row_id in (0..256u64).rev() {
395 t.insert(v(5), row_id);
396 }
397 assert_eq!(t.lookup_eq(&v(5)), (0..256u64).collect::<Vec<_>>());
398 assert!(t.contains(&v(5), 127));
399 assert!(t.delete(&v(5), 127));
400 assert!(!t.contains(&v(5), 127));
401 assert_eq!(t.lookup_eq(&v(5)).len(), 255);
402 }
403
404 #[test]
405 fn delete_leaves_and_reuses_tombstone_order() {
406 let mut t = BTree::default();
407 for row_id in 0..512u64 {
408 t.insert(v(row_id as i64), row_id);
409 }
410 for row_id in 0..512u64 {
411 assert!(t.delete(&v(row_id as i64), row_id));
412 }
413 for row_id in (0..128u64).rev() {
414 t.insert(v(9), row_id);
415 }
416 assert_eq!(t.lookup_eq(&v(9)), (0..128u64).collect::<Vec<_>>());
417 }
418
419 #[test]
420 fn delete_and_shrink() {
421 let mut t = BTree::default();
422 for i in 0..200 {
423 t.insert(v(i), i as u64);
424 }
425 for i in 0..200 {
426 assert!(t.delete(&v(i), i as u64));
427 }
428 assert!(t.is_empty());
429 t.insert(v(1), 1);
430 assert_eq!(t.lookup_eq(&v(1)), vec![1]);
431 }
432
433 #[test]
434 fn scan_all_order() {
435 let mut t = BTree::default();
436 let mut expect = Vec::new();
437 for i in 0..300 {
438 t.insert(v(i), i as u64);
439 expect.push((v(i), i as u64));
440 }
441 assert_eq!(t.scan_all(), expect);
442 }
443
444 #[test]
445 fn text_and_null_keys() {
446 let mut t = BTree::default();
447 t.insert(Value::Text("b".into()), 1);
448 t.insert(Value::Text("a".into()), 2);
449 t.insert(Value::Null, 3);
450 let all = t.scan_all();
451 assert_eq!(all[0].1, 3); assert_eq!(all[1].1, 2);
453 assert_eq!(all[2].1, 1);
454 }
455
456 #[test]
457 fn randomized_delete_preserves_order_and_lookup() {
458 let mut tree = BTree::default();
459 for id in 0..2000u64 {
460 let key = ((id * 1103515245 + 12345) % 10000) as i64;
461 tree.insert(v(key), id);
462 }
463 let mut expected = tree.scan_all();
464 for id in (0..2000u64).step_by(3) {
465 let key = ((id * 1103515245 + 12345) % 10000) as i64;
466 assert!(tree.delete(&v(key), id));
467 expected.retain(|(_, row_id)| *row_id != id);
468 }
469 expected.sort_by(|left, right| cmp_entry(&left.0, left.1, &right.0, right.1));
470 assert_eq!(tree.scan_all(), expected);
471 for (key, id) in expected {
472 assert!(tree.contains(&key, id));
473 }
474 }
475
476 #[test]
477 fn mixed_insert_delete_matches_sorted_model() {
478 let mut tree = BTree::default();
479 let mut model: Vec<(Value, u64)> = Vec::new();
480 for step in 0..3000u64 {
481 let row_id = (step * 37) % 701;
482 let key = v(((step * 97) % 23) as i64);
483 if step % 3 == 0 {
484 let removed = tree.delete(&key, row_id);
485 let before = model.len();
486 model.retain(|entry| entry != &(key.clone(), row_id));
487 assert_eq!(removed, model.len() != before);
488 } else {
489 tree.insert(key.clone(), row_id);
490 if !model.contains(&(key, row_id)) {
491 model.push((v(((step * 97) % 23) as i64), row_id));
492 }
493 }
494 model.sort_by(|left, right| cmp_entry(&left.0, left.1, &right.0, right.1));
495 assert_eq!(tree.scan_all(), model);
496 }
497 }
498}