1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::{
index::{AnyIndex, IndexType},
table::TableType,
Index,
};
/// Represents a constraint on a typed table.
pub struct Constraint<T: TableType + 'static>(pub(crate) ConstraintInner<T>);
pub(crate) enum ConstraintInner<T: TableType + 'static> {
/// Unique constraint based on index.
Unique(Box<dyn AnyIndex<T>>),
/// Constraint based on closure check.
Check(fn(&T) -> bool),
}
impl<T: TableType> Constraint<T> {
/// Creates a new unique constraint using the given index.
///
/// # Arguments
///
/// * `index` - A reference to the [`Index`] instance to be used for enforcing the unique constraint.
pub fn unique<I: IndexType + 'static>(index: &Index<T, I>) -> Self {
Self(ConstraintInner::Unique(Box::new(index.clone())))
}
/// Creates a new constraint based on a custom check function.
///
/// # Arguments
///
/// * `check` - A function that takes a reference to the value `T` and returns a boolean indicating if the constraint is satisfied.
pub fn check(check: fn(&T) -> bool) -> Self {
Self(ConstraintInner::Check(check))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{result::TinyBaseError, Table, TinyBase};
#[test]
fn table_constraint() {
let db = TinyBase::new(None, true);
let table: Table<String> = db.open_table("test_table").unwrap();
// Create an index for the constraint
let index = table
.create_index("name", |value| value.to_owned())
.unwrap();
// Add unique constraint with created index
assert!(table.constraint(Constraint::unique(&index)).is_ok());
// Add check constraint with condition
assert!(table
.constraint(Constraint::check(|value: &String| value.len() >= 5))
.is_ok());
table.insert("greater".to_owned()).unwrap();
// Unique constraint.
assert!(matches!(
table.insert("greater".to_owned()),
Err(TinyBaseError::Exists { .. })
));
// Check constraint.
assert!(matches!(
table.insert("less".to_owned()),
Err(TinyBaseError::Condition)
));
}
}