1use std::collections::{HashMap, HashSet};
8
9use crate::btree::BTree;
10use crate::types::{ColumnType, Value};
11
12pub type Row = Vec<Value>;
13
14#[derive(Debug, Clone)]
15pub struct Column {
16 pub name: String,
17 pub ty: ColumnType,
18 pub not_null: bool,
19 pub unique: bool,
20 pub primary_key: bool,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum DbErrorKind {
25 UnknownTable,
26 DuplicateColumn,
27 Constraint,
28 TypeMismatch,
29 Syntax(String),
30 NotNull,
31 UnknownColumn,
32 ColumnCount,
33 Io(String),
34 Busy,
35 Transaction,
36 Limit,
37 Internal(String),
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct DbError {
42 pub kind: DbErrorKind,
43 pub message: String,
44}
45
46impl DbError {
47 pub fn new(kind: DbErrorKind, message: impl Into<String>) -> DbError {
48 DbError {
49 kind,
50 message: message.into(),
51 }
52 }
53}
54
55impl std::fmt::Display for DbError {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 write!(f, "{}", self.message)
58 }
59}
60
61impl std::error::Error for DbError {}
62
63#[derive(Debug, Clone)]
65pub struct State {
66 pub tables: HashMap<String, Table>,
67}
68
69impl State {
70 pub fn empty() -> State {
71 State {
72 tables: HashMap::new(),
73 }
74 }
75
76 pub fn table(&self, name: &str) -> Option<&Table> {
77 self.tables
78 .iter()
79 .find(|(key, _)| key.eq_ignore_ascii_case(name))
80 .map(|(_, table)| table)
81 }
82
83 pub fn table_mut(&mut self, name: &str) -> Option<&mut Table> {
84 let key = self
85 .tables
86 .keys()
87 .find(|key| key.eq_ignore_ascii_case(name))?
88 .clone();
89 self.tables.get_mut(&key)
90 }
91
92 pub fn contains_table(&self, name: &str) -> bool {
93 self.table(name).is_some()
94 }
95
96 pub fn contains_index(&self, name: &str) -> bool {
97 self.tables.values().any(|table| table.has_index(name))
98 }
99
100 pub fn remove_table(&mut self, name: &str) -> Option<Table> {
101 let key = self
102 .tables
103 .keys()
104 .find(|key| key.eq_ignore_ascii_case(name))?
105 .clone();
106 self.tables.remove(&key)
107 }
108
109 pub(crate) fn encode(&self) -> Vec<u8> {
112 let mut w = BinWriter::default();
113 w.bytes(b"BSS1");
114 w.u32(1);
115 let mut names: Vec<&String> = self.tables.keys().collect();
116 names.sort();
117 w.u32(names.len() as u32);
118 for name in names {
119 let table = &self.tables[name];
120 w.string(&table.name);
121 w.u32(table.columns.len() as u32);
122 for column in &table.columns {
123 w.string(&column.name);
124 w.u8(column_type_tag(&column.ty));
125 let mut flags = 0u8;
126 if column.not_null {
127 flags |= 1;
128 }
129 if column.unique {
130 flags |= 2;
131 }
132 if column.primary_key {
133 flags |= 4;
134 }
135 w.u8(flags);
136 }
137 w.u32(table.indexes.len() as u32);
138 for index in &table.indexes {
139 w.string(&index.name);
140 w.u32(index.column as u32);
141 w.u8(index.unique as u8);
142 }
143 w.u64(table.row_seq);
144 w.u32(table.rows.len() as u32);
145 for row in &table.rows {
146 match row {
147 None => w.u8(0),
148 Some(values) => {
149 w.u8(1);
150 w.u32(values.len() as u32);
151 for value in values {
152 encode_value(&mut w, value);
153 }
154 }
155 }
156 }
157 }
158 w.finish()
159 }
160
161 pub(crate) fn decode(bytes: &[u8]) -> Result<State, DbError> {
164 let mut r = BinReader::new(bytes);
165 if r.bytes(4)? != b"BSS1" {
166 return Err(dberr(
167 DbErrorKind::Io("invalid state magic".into()),
168 "corrupt database: invalid state magic",
169 ));
170 }
171 if r.u32()? != 1 {
172 return Err(dberr(
173 DbErrorKind::Io("unsupported state version".into()),
174 "corrupt database: unsupported state version",
175 ));
176 }
177 let table_count = r.count("table")?;
178 let mut tables: HashMap<String, Table> = HashMap::new();
179 let mut index_names = HashSet::new();
180 for _ in 0..table_count {
181 let name = r.string("table name")?;
182 if tables
183 .keys()
184 .any(|existing| existing.eq_ignore_ascii_case(&name))
185 {
186 return Err(dberr(
187 DbErrorKind::Io("duplicate table name".into()),
188 format!("corrupt database: duplicate table '{name}'"),
189 ));
190 }
191 let column_count = r.count("column")?;
192 let mut columns = Vec::with_capacity(column_count);
193 for _ in 0..column_count {
194 let column_name = r.string("column name")?;
195 let ty = column_type_from_tag(r.u8()?)?;
196 let flags = r.u8()?;
197 if flags & !0b111 != 0 {
198 return Err(dberr(
199 DbErrorKind::Io("invalid column flags".into()),
200 "corrupt database: invalid column flags",
201 ));
202 }
203 columns.push(Column {
204 name: column_name,
205 ty,
206 not_null: flags & 1 != 0,
207 unique: flags & 2 != 0,
208 primary_key: flags & 4 != 0,
209 });
210 }
211 let index_count = r.count("index")?;
212 let mut index_defs = Vec::with_capacity(index_count);
213 for _ in 0..index_count {
214 let index_name = r.string("index name")?;
215 let column = r.u32()? as usize;
216 let unique = match r.u8()? {
217 0 => false,
218 1 => true,
219 _ => {
220 return Err(dberr(
221 DbErrorKind::Io("invalid index uniqueness flag".into()),
222 "corrupt database: invalid index uniqueness flag",
223 ));
224 }
225 };
226 index_defs.push((index_name, column, unique));
227 }
228 let row_seq = r.u64()?;
229 let slot_count = r.count("row slot")?;
230 if row_seq != slot_count as u64 {
231 return Err(dberr(
232 DbErrorKind::Io("row sequence does not match slot array".into()),
233 format!("corrupt database: invalid row sequence for table '{name}'"),
234 ));
235 }
236 let mut table = Table::new(&name, columns)?;
237 let mut live = 0usize;
238 table.rows.reserve(slot_count);
239 for _ in 0..slot_count {
240 match r.u8()? {
241 0 => table.rows.push(None),
242 1 => {
243 let value_count = r.count("row value")?;
244 if value_count != table.columns.len() {
245 return Err(dberr(
246 DbErrorKind::Io("row width does not match table".into()),
247 format!("corrupt database: invalid row width in table '{name}'"),
248 ));
249 }
250 let mut row = Vec::with_capacity(value_count);
251 for _ in 0..value_count {
252 row.push(decode_value(&mut r)?);
253 }
254 for (idx, column) in table.columns.iter().enumerate() {
255 if (column.not_null || column.primary_key)
256 && matches!(row[idx], Value::Null)
257 {
258 return Err(dberr(
259 DbErrorKind::Io("stored NULL violates NOT NULL".into()),
260 format!("corrupt database: NULL in '{}'", column.name),
261 ));
262 }
263 row[idx] = row[idx].coerce_to(&column.ty).map_err(|e| {
264 dberr(
265 DbErrorKind::Io(e.clone()),
266 format!(
267 "corrupt database: invalid value in '{}': {e}",
268 column.name
269 ),
270 )
271 })?;
272 }
273 table.rows.push(Some(row));
274 live += 1;
275 }
276 _ => {
277 return Err(dberr(
278 DbErrorKind::Io("invalid row slot marker".into()),
279 format!("corrupt database: invalid row slot in table '{name}'"),
280 ));
281 }
282 }
283 }
284 table.row_seq = row_seq;
285 table.live = live;
286 table.rebuild_indexes();
287 for (index_name, column, unique) in index_defs {
288 if !index_names.insert(index_name.to_ascii_lowercase()) {
289 return Err(dberr(
290 DbErrorKind::Io("duplicate index name".into()),
291 format!("corrupt database: duplicate index '{index_name}'"),
292 ));
293 }
294 table.create_index(&index_name, column, unique)?;
295 }
296 table.validate_indexes()?;
297 tables.insert(name, table);
298 }
299 if !r.at_end() {
300 return Err(dberr(
301 DbErrorKind::Io("trailing state bytes".into()),
302 "corrupt database: trailing state bytes",
303 ));
304 }
305 Ok(State { tables })
306 }
307}
308
309#[derive(Debug, Clone)]
311pub enum StatementResult {
312 Select {
313 columns: Vec<String>,
314 rows: Vec<Row>,
315 },
316 Insert {
317 rows_affected: usize,
318 },
319 Update {
320 rows_affected: usize,
321 },
322 Delete {
323 rows_affected: usize,
324 },
325 CreateTable {
326 name: String,
327 },
328 DropTable {
329 name: String,
330 },
331 CreateIndex {
332 name: String,
333 table: String,
334 column: String,
335 },
336 DropIndex {
337 name: String,
338 },
339 Explain(String),
340 Begin,
341 Commit,
342 Rollback,
343 Checkpoint,
344 Echo(String),
345}
346
347#[derive(Debug, Clone)]
348pub struct Table {
349 pub name: String,
350 pub columns: Vec<Column>,
351 rows: Vec<Option<Row>>,
352 row_seq: u64,
353 live: usize,
354 pk: Option<BTree>,
356 uniques: Vec<(usize, BTree)>,
358 indexes: Vec<Index>,
360}
361
362#[derive(Debug, Clone)]
363pub struct Index {
364 pub name: String,
365 pub column: usize,
366 pub unique: bool,
367 pub(crate) tree: BTree,
368}
369
370impl Table {
371 pub fn new(name: &str, columns: Vec<Column>) -> Result<Table, DbError> {
372 let mut seen = HashMap::new();
373 let mut pk: Option<BTree> = None;
374 let mut uniques = Vec::new();
375 let mut primary_count = 0usize;
376 for (i, c) in columns.iter().enumerate() {
377 if seen.insert(c.name.to_ascii_lowercase(), ()).is_some() {
378 return Err(DbError::new(
379 DbErrorKind::DuplicateColumn,
380 format!("duplicate column name '{}'", c.name),
381 ));
382 }
383 if c.primary_key && c.ty != ColumnType::Integer {
384 return Err(DbError::new(
385 DbErrorKind::Constraint,
386 "PRIMARY KEY column must be INTEGER".to_string(),
387 ));
388 }
389 if c.primary_key {
390 primary_count += 1;
391 pk = Some(BTree::default());
392 }
393 if c.unique && !c.primary_key {
394 uniques.push((i, BTree::default()));
395 }
396 }
397 if primary_count > 1 {
398 return Err(DbError::new(
399 DbErrorKind::Constraint,
400 "only one PRIMARY KEY column is supported",
401 ));
402 }
403 Ok(Table {
404 name: name.to_string(),
405 columns,
406 rows: Vec::new(),
407 row_seq: 0,
408 live: 0,
409 pk,
410 uniques,
411 indexes: Vec::new(),
412 })
413 }
414
415 pub fn row_count(&self) -> usize {
416 self.live
417 }
418
419 pub fn column_index(&self, name: &str) -> Result<usize, DbError> {
420 self.columns
421 .iter()
422 .position(|c| c.name.eq_ignore_ascii_case(name))
423 .ok_or_else(|| {
424 DbError::new(
425 DbErrorKind::UnknownColumn,
426 format!("no such column: {name}"),
427 )
428 })
429 }
430
431 pub fn coerce_val(&self, val: &Value, col_idx: usize) -> Result<Value, DbError> {
432 let ty = &self.columns[col_idx].ty;
433 val.coerce_to(ty).map_err(|e| {
434 DbError::new(
435 DbErrorKind::TypeMismatch,
436 format!("column '{}': {e}", self.columns[col_idx].name),
437 )
438 })
439 }
440
441 fn alloc_slot(&mut self) -> u64 {
443 if let Some((i, slot)) = self.rows.iter_mut().enumerate().find(|(_, r)| r.is_none()) {
444 *slot = Some(Vec::new());
445 return i as u64;
446 }
447 let id = self.row_seq;
448 self.row_seq += 1;
449 self.rows.push(Some(Vec::new()));
450 id
451 }
452
453 fn pk_col_idx(&self) -> Option<usize> {
454 self.columns.iter().position(|c| c.primary_key)
455 }
456
457 pub fn insert_row(&mut self, values: Vec<Value>) -> Result<u64, DbError> {
459 if values.len() != self.columns.len() {
460 return Err(DbError::new(
461 DbErrorKind::ColumnCount,
462 format!(
463 "column count mismatch: expected {}, got {}",
464 self.columns.len(),
465 values.len()
466 ),
467 ));
468 }
469 self.validate_row(&values, None)?;
470 let rid = self.alloc_slot();
471 self.rows[rid as usize] = Some(values.clone());
472 self.live += 1;
473 let pk_idx = self.pk_col_idx();
474 if let Some(pk) = &mut self.pk {
475 let pk_idx = pk_idx.expect("has pk");
476 pk.insert(values[pk_idx].clone(), rid);
477 }
478 for (idx, tree) in &mut self.uniques {
479 let k = values[*idx].clone();
480 if !matches!(k, Value::Null) {
481 tree.insert(k, rid);
482 }
483 }
484 for index in &mut self.indexes {
485 let key = values[index.column].clone();
486 if !index.unique || !matches!(key, Value::Null) {
487 index.tree.insert(key, rid);
488 }
489 }
490 Ok(rid)
491 }
492
493 pub fn delete_row(&mut self, rid: u64) -> Result<(), DbError> {
495 let idx = rid as usize;
496 if idx >= self.rows.len() || self.rows[idx].is_none() {
497 return Err(dberr(
498 DbErrorKind::Internal(format!("no such row id {rid}")),
499 format!("no such row id {rid}"),
500 ));
501 }
502 let row = self.rows[idx].take().unwrap();
503 self.live -= 1;
504 if self.pk.is_some() {
505 let pk_idx = self.pk_col_idx().expect("has pk");
506 if let Some(pk) = self.pk.as_mut() {
507 pk.delete(&row[pk_idx], rid);
508 }
509 }
510 for (cidx, tree) in &mut self.uniques {
511 let k = row[*cidx].clone();
512 if !matches!(k, Value::Null) {
513 tree.delete(&k, rid);
514 }
515 }
516 for index in &mut self.indexes {
517 index.tree.delete(&row[index.column], rid);
518 }
519 Ok(())
520 }
521
522 pub fn get_row(&self, rid: u64) -> Option<&Row> {
524 let idx = rid as usize;
525 self.rows.get(idx).and_then(|r| r.as_ref())
526 }
527
528 pub fn scan(&self) -> impl Iterator<Item = (u64, &Row)> {
530 self.rows
531 .iter()
532 .enumerate()
533 .filter_map(|(i, r)| r.as_ref().map(|row| (i as u64, row)))
534 }
535 pub fn replace_row(&mut self, rid: u64, new: Vec<Value>) -> Result<(), DbError> {
538 let idx = rid as usize;
539 if idx >= self.rows.len() || self.rows[idx].is_none() {
540 return Err(dberr(
541 DbErrorKind::Internal(format!("no such row id {rid}")),
542 format!("no such row id {rid}"),
543 ));
544 }
545 if new.len() != self.columns.len() {
546 return Err(dberr(
547 DbErrorKind::ColumnCount,
548 format!(
549 "column count mismatch: expected {}, got {}",
550 self.columns.len(),
551 new.len()
552 ),
553 ));
554 }
555 self.validate_row(&new, Some(rid))?;
556 let old = self.rows[idx].take().unwrap();
557 if self.pk.is_some() {
558 let pk_idx = self.pk_col_idx().expect("has pk");
559 if let Some(pk) = self.pk.as_mut() {
560 pk.delete(&old[pk_idx], rid);
561 }
562 }
563 for (cidx, tree) in &mut self.uniques {
564 let k = old[*cidx].clone();
565 if !matches!(k, Value::Null) {
566 tree.delete(&k, rid);
567 }
568 }
569 for index in &mut self.indexes {
570 index.tree.delete(&old[index.column], rid);
571 }
572 if self.pk.is_some() {
573 let pk_idx = self.pk_col_idx().expect("has pk");
574 if let Some(pk) = self.pk.as_mut() {
575 pk.insert(new[pk_idx].clone(), rid);
576 }
577 }
578 for (cidx, tree) in &mut self.uniques {
579 let k = new[*cidx].clone();
580 if !matches!(k, Value::Null) {
581 tree.insert(k, rid);
582 }
583 }
584 for index in &mut self.indexes {
585 let key = new[index.column].clone();
586 if !index.unique || !matches!(key, Value::Null) {
587 index.tree.insert(key, rid);
588 }
589 }
590 self.rows[idx] = Some(new);
591 Ok(())
592 }
593
594 pub fn rebuild_indexes(&mut self) {
597 if self.pk.is_some() {
598 self.pk = Some(BTree::default());
599 }
600 self.uniques = self
601 .uniques
602 .drain(..)
603 .map(|(i, _)| (i, BTree::default()))
604 .collect();
605 for index in &mut self.indexes {
606 index.tree = BTree::default();
607 }
608 let live: Vec<(u64, Row)> = self.scan().map(|(r, row)| (r, row.clone())).collect();
609 for (rid, row) in live {
610 if self.pk.is_some() {
611 let pk_idx = self.pk_col_idx().expect("has pk");
612 if let Some(pk) = self.pk.as_mut() {
613 pk.insert(row[pk_idx].clone(), rid);
614 }
615 }
616 for (cidx, tree) in &mut self.uniques {
617 let k = row[*cidx].clone();
618 if !matches!(k, Value::Null) {
619 tree.insert(k, rid);
620 }
621 }
622 for index in &mut self.indexes {
623 let key = row[index.column].clone();
624 if !index.unique || !matches!(key, Value::Null) {
625 index.tree.insert(key, rid);
626 }
627 }
628 }
629 }
630
631 pub fn has_pk(&self, v: &Value) -> bool {
632 self.pk
633 .as_ref()
634 .map(|t| !t.lookup_eq(v).is_empty())
635 .unwrap_or(false)
636 }
637
638 pub fn unique_tree(&self, col_idx: usize) -> Option<&BTree> {
639 self.uniques
640 .iter()
641 .find(|(i, _)| *i == col_idx)
642 .map(|(_, t)| t)
643 }
644
645 pub fn create_index(&mut self, name: &str, column: usize, unique: bool) -> Result<(), DbError> {
646 if self
647 .indexes
648 .iter()
649 .any(|index| index.name.eq_ignore_ascii_case(name))
650 {
651 return Err(dberr(
652 DbErrorKind::Constraint,
653 format!("index '{name}' already exists"),
654 ));
655 }
656 if column >= self.columns.len() {
657 return Err(dberr(
658 DbErrorKind::UnknownColumn,
659 format!("no such column index: {column}"),
660 ));
661 }
662 let mut index = Index {
663 name: name.to_string(),
664 column,
665 unique,
666 tree: BTree::default(),
667 };
668 for (rid, row) in self.scan() {
669 let key = row[column].clone();
670 if unique && !matches!(key, Value::Null) && !index.tree.lookup_eq(&key).is_empty() {
671 return Err(dberr(
672 DbErrorKind::Constraint,
673 format!("UNIQUE index '{name}' has duplicate value: {key}"),
674 ));
675 }
676 if !unique || !matches!(key, Value::Null) {
677 index.tree.insert(key, rid);
678 }
679 }
680 self.indexes.push(index);
681 Ok(())
682 }
683
684 pub fn drop_index(&mut self, name: &str) -> bool {
685 if let Some(position) = self
686 .indexes
687 .iter()
688 .position(|index| index.name.eq_ignore_ascii_case(name))
689 {
690 self.indexes.remove(position);
691 true
692 } else {
693 false
694 }
695 }
696
697 pub fn has_index(&self, name: &str) -> bool {
698 self.indexes
699 .iter()
700 .any(|index| index.name.eq_ignore_ascii_case(name))
701 }
702
703 pub fn index(&self, column: usize) -> Option<&Index> {
704 self.indexes.iter().find(|index| index.column == column)
705 }
706
707 pub fn lookup_eq_index(&self, column: usize, key: &Value) -> Option<(String, Vec<u64>)> {
709 if self.pk_col_idx() == Some(column) {
710 return self
711 .pk
712 .as_ref()
713 .map(|tree| ("PRIMARY KEY".into(), tree.lookup_eq(key)));
714 }
715 if let Some((_, tree)) = self.uniques.iter().find(|(idx, _)| *idx == column) {
716 return Some((
717 format!("UNIQUE({})", self.columns[column].name),
718 tree.lookup_eq(key),
719 ));
720 }
721 self.index(column)
722 .map(|index| (index.name.clone(), index.tree.lookup_eq(key)))
723 }
724
725 pub fn lookup_range_index(
728 &self,
729 column: usize,
730 low: Option<&Value>,
731 high: Option<&Value>,
732 ) -> Option<(String, Vec<u64>)> {
733 let (name, entries) = if self.pk_col_idx() == Some(column) {
734 ("PRIMARY KEY".to_string(), self.pk.as_ref()?.scan_all())
735 } else if let Some((_, tree)) = self.uniques.iter().find(|(idx, _)| *idx == column) {
736 (
737 format!("UNIQUE({})", self.columns[column].name),
738 tree.scan_all(),
739 )
740 } else {
741 let index = self.index(column)?;
742 (index.name.clone(), index.tree.scan_all())
743 };
744 let row_ids = entries
745 .into_iter()
746 .filter(|(key, _)| {
747 low.map(|bound| key.cmp_value(bound) != std::cmp::Ordering::Less)
748 .unwrap_or(true)
749 && high
750 .map(|bound| key.cmp_value(bound) != std::cmp::Ordering::Greater)
751 .unwrap_or(true)
752 })
753 .map(|(_, row_id)| row_id)
754 .collect();
755 Some((name, row_ids))
756 }
757
758 fn validate_row(&self, values: &[Value], ignore_rid: Option<u64>) -> Result<(), DbError> {
759 for (i, column) in self.columns.iter().enumerate() {
760 if (column.not_null || column.primary_key) && matches!(values[i], Value::Null) {
761 return Err(DbError::new(
762 DbErrorKind::NotNull,
763 format!("column '{}' violates NOT NULL", column.name),
764 ));
765 }
766 if column.ty == ColumnType::Real
767 && matches!(values[i], Value::Real(value) if !value.is_finite())
768 {
769 return Err(DbError::new(
770 DbErrorKind::TypeMismatch,
771 format!("column '{}' cannot store a non-finite REAL", column.name),
772 ));
773 }
774 }
775 if let Some(pk) = &self.pk {
776 let idx = self.pk_col_idx().expect("has pk");
777 if pk
778 .lookup_eq(&values[idx])
779 .into_iter()
780 .any(|rid| Some(rid) != ignore_rid)
781 {
782 return Err(DbError::new(
783 DbErrorKind::Constraint,
784 format!(
785 "UNIQUE constraint failed (PRIMARY KEY): {} already exists",
786 values[idx]
787 ),
788 ));
789 }
790 }
791 for (idx, tree) in &self.uniques {
792 let key = &values[*idx];
793 if !matches!(key, Value::Null)
794 && tree
795 .lookup_eq(key)
796 .into_iter()
797 .any(|rid| Some(rid) != ignore_rid)
798 {
799 return Err(DbError::new(
800 DbErrorKind::Constraint,
801 format!(
802 "UNIQUE constraint failed on '{}': {key} already exists",
803 self.columns[*idx].name
804 ),
805 ));
806 }
807 }
808 for index in &self.indexes {
809 let key = &values[index.column];
810 if index.unique
811 && !matches!(key, Value::Null)
812 && index
813 .tree
814 .lookup_eq(key)
815 .into_iter()
816 .any(|rid| Some(rid) != ignore_rid)
817 {
818 return Err(DbError::new(
819 DbErrorKind::Constraint,
820 format!(
821 "UNIQUE constraint failed on index '{}': {key} already exists",
822 index.name
823 ),
824 ));
825 }
826 }
827 Ok(())
828 }
829
830 fn validate_indexes(&self) -> Result<(), DbError> {
831 if let Some(pk) = &self.pk
832 && pk
833 .scan_all()
834 .windows(2)
835 .any(|pair| pair[0].0.cmp_value(&pair[1].0) == std::cmp::Ordering::Equal)
836 {
837 return Err(dberr(
838 DbErrorKind::Io("duplicate primary key".into()),
839 format!(
840 "corrupt database: duplicate primary key in table '{}'",
841 self.name
842 ),
843 ));
844 }
845 for (idx, tree) in &self.uniques {
846 if tree
847 .scan_all()
848 .windows(2)
849 .any(|pair| pair[0].0.cmp_value(&pair[1].0) == std::cmp::Ordering::Equal)
850 {
851 return Err(dberr(
852 DbErrorKind::Io("duplicate unique value".into()),
853 format!(
854 "corrupt database: duplicate unique value in '{}.{}'",
855 self.name, self.columns[*idx].name
856 ),
857 ));
858 }
859 }
860 for index in &self.indexes {
861 if index.unique
862 && index
863 .tree
864 .scan_all()
865 .windows(2)
866 .any(|pair| pair[0].0.cmp_value(&pair[1].0) == std::cmp::Ordering::Equal)
867 {
868 return Err(dberr(
869 DbErrorKind::Io("duplicate unique index value".into()),
870 format!(
871 "corrupt database: duplicate value in index '{}.{}'",
872 self.name, index.name
873 ),
874 ));
875 }
876 }
877 Ok(())
878 }
879}
880
881#[derive(Default)]
882struct BinWriter {
883 bytes: Vec<u8>,
884}
885
886impl BinWriter {
887 fn bytes(&mut self, value: &[u8]) {
888 self.bytes.extend_from_slice(value);
889 }
890
891 fn finish(self) -> Vec<u8> {
892 self.bytes
893 }
894
895 fn u8(&mut self, value: u8) {
896 self.bytes.push(value);
897 }
898
899 fn u32(&mut self, value: u32) {
900 self.bytes.extend_from_slice(&value.to_le_bytes());
901 }
902
903 fn u64(&mut self, value: u64) {
904 self.bytes.extend_from_slice(&value.to_le_bytes());
905 }
906
907 fn string(&mut self, value: &str) {
908 self.u32(value.len() as u32);
909 self.bytes(value.as_bytes());
910 }
911}
912
913struct BinReader<'a> {
914 bytes: &'a [u8],
915 pos: usize,
916}
917
918impl<'a> BinReader<'a> {
919 fn new(bytes: &'a [u8]) -> BinReader<'a> {
920 BinReader { bytes, pos: 0 }
921 }
922
923 fn at_end(&self) -> bool {
924 self.pos == self.bytes.len()
925 }
926
927 fn take(&mut self, len: usize, what: &str) -> Result<&'a [u8], DbError> {
928 let end = self.pos.checked_add(len).ok_or_else(|| {
929 dberr(
930 DbErrorKind::Io("state offset overflow".into()),
931 format!("corrupt database: state offset overflow while reading {what}"),
932 )
933 })?;
934 let value = self.bytes.get(self.pos..end).ok_or_else(|| {
935 dberr(
936 DbErrorKind::Io("truncated state".into()),
937 format!("corrupt database: truncated state while reading {what}"),
938 )
939 })?;
940 self.pos = end;
941 Ok(value)
942 }
943
944 fn bytes(&mut self, len: usize) -> Result<&'a [u8], DbError> {
945 self.take(len, "bytes")
946 }
947
948 fn u8(&mut self) -> Result<u8, DbError> {
949 Ok(self.take(1, "byte")?[0])
950 }
951
952 fn u32(&mut self) -> Result<u32, DbError> {
953 Ok(u32::from_le_bytes(self.take(4, "u32")?.try_into().unwrap()))
954 }
955
956 fn u64(&mut self) -> Result<u64, DbError> {
957 Ok(u64::from_le_bytes(self.take(8, "u64")?.try_into().unwrap()))
958 }
959
960 fn count(&mut self, what: &str) -> Result<usize, DbError> {
961 let count = self.u32()? as usize;
962 if count > 1_000_000 {
963 return Err(dberr(
964 DbErrorKind::Io("state collection is too large".into()),
965 format!("corrupt database: too many {what}s"),
966 ));
967 }
968 Ok(count)
969 }
970
971 fn string(&mut self, what: &str) -> Result<String, DbError> {
972 let len = self.u32()? as usize;
973 if len > 64 * 1024 * 1024 {
974 return Err(dberr(
975 DbErrorKind::Io("state string is too large".into()),
976 format!("corrupt database: {what} is too large"),
977 ));
978 }
979 let bytes = self.take(len, what)?;
980 String::from_utf8(bytes.to_vec()).map_err(|_| {
981 dberr(
982 DbErrorKind::Io("invalid UTF-8 in state".into()),
983 format!("corrupt database: invalid UTF-8 in {what}"),
984 )
985 })
986 }
987}
988
989fn column_type_tag(ty: &ColumnType) -> u8 {
990 match ty {
991 ColumnType::Integer => 0,
992 ColumnType::Real => 1,
993 ColumnType::Text => 2,
994 ColumnType::Boolean => 3,
995 ColumnType::Any => 4,
996 ColumnType::Null => 5,
997 }
998}
999
1000fn column_type_from_tag(tag: u8) -> Result<ColumnType, DbError> {
1001 match tag {
1002 0 => Ok(ColumnType::Integer),
1003 1 => Ok(ColumnType::Real),
1004 2 => Ok(ColumnType::Text),
1005 3 => Ok(ColumnType::Boolean),
1006 4 => Ok(ColumnType::Any),
1007 5 => Ok(ColumnType::Null),
1008 _ => Err(dberr(
1009 DbErrorKind::Io("invalid column type".into()),
1010 "corrupt database: invalid column type",
1011 )),
1012 }
1013}
1014
1015fn encode_value(w: &mut BinWriter, value: &Value) {
1016 match value {
1017 Value::Null => w.u8(0),
1018 Value::Integer(v) => {
1019 w.u8(1);
1020 w.u64(*v as u64);
1021 }
1022 Value::Real(v) => {
1023 w.u8(2);
1024 w.u64(v.to_bits());
1025 }
1026 Value::Text(v) => {
1027 w.u8(3);
1028 w.string(v);
1029 }
1030 Value::Boolean(v) => {
1031 w.u8(4);
1032 w.u8(*v as u8);
1033 }
1034 }
1035}
1036
1037fn decode_value(r: &mut BinReader<'_>) -> Result<Value, DbError> {
1038 match r.u8()? {
1039 0 => Ok(Value::Null),
1040 1 => Ok(Value::Integer(r.u64()? as i64)),
1041 2 => Ok(Value::Real(f64::from_bits(r.u64()?))),
1042 3 => Ok(Value::Text(r.string("text value")?)),
1043 4 => match r.u8()? {
1044 0 => Ok(Value::Boolean(false)),
1045 1 => Ok(Value::Boolean(true)),
1046 _ => Err(dberr(
1047 DbErrorKind::Io("invalid boolean".into()),
1048 "corrupt database: invalid boolean value",
1049 )),
1050 },
1051 _ => Err(dberr(
1052 DbErrorKind::Io("invalid value tag".into()),
1053 "corrupt database: invalid value tag",
1054 )),
1055 }
1056}
1057
1058pub fn dberr(kind: DbErrorKind, msg: impl Into<String>) -> DbError {
1059 DbError::new(kind, msg)
1060}