taple_core/database/
mod.rs

1mod db;
2mod error;
3mod layers;
4mod memory;
5
6pub use self::memory::{MemoryCollection, MemoryManager};
7pub use db::DB;
8pub use error::Error;
9
10/// Trait to define a database compatible with Taple
11pub trait DatabaseManager<C>: Sync + Send
12where
13    C: DatabaseCollection,
14{
15    /// Default constructor for the database manager. Is is mainly used for the battery test
16    fn default() -> Self;
17    /// Creates a database collection
18    /// # Arguments
19    /// - identifier: The identifier of the collection
20    fn create_collection(&self, identifier: &str) -> C;
21}
22
23/// A trait representing a collection of key-value pairs in a database.
24pub trait DatabaseCollection: Sync + Send {
25    /// Retrieves the value associated with the given key.
26    fn get(&self, key: &str) -> Result<Vec<u8>, Error>;
27    /// Associates the given value with the given key.
28    fn put(&self, key: &str, data: Vec<u8>) -> Result<(), Error>;
29    /// Removes the value associated with the given key.
30    fn del(&self, key: &str) -> Result<(), Error>;
31    /// Returns an iterator over the key-value pairs in the collection.
32    fn iter<'a>(
33        &'a self,
34        reverse: bool,
35        prefix: String,
36    ) -> Box<dyn Iterator<Item = (String, Vec<u8>)> + 'a>;
37}
38
39/// Allows a TAPLE database implementation to be subjected to a battery of tests.
40/// The use must specify both a valid implementation of [DatabaseManager] and [DatabaseCollection]
41/// # Example
42/// ```rs
43/// test_database_manager_trait! {
44///    unit_test_memory_manager:crate::MemoryManager:MemoryCollection
45/// }
46/// ```
47#[macro_export]
48macro_rules! test_database_manager_trait {
49    ($name:ident: $type:ty: $type2:ty) => {
50        mod $name {
51            #[allow(unused_imports)]
52            use super::*;
53            use borsh::{BorshDeserialize, BorshSerialize};
54
55            #[derive(BorshSerialize, BorshDeserialize, Clone, PartialEq, Eq, Debug)]
56            struct Data {
57                id: usize,
58                value: String,
59            }
60
61            #[allow(dead_code)]
62            fn get_data() -> Result<Vec<Vec<u8>>, Error> {
63                let data1 = Data {
64                    id: 1,
65                    value: "A".into(),
66                };
67                let data2 = Data {
68                    id: 2,
69                    value: "B".into(),
70                };
71                let data3 = Data {
72                    id: 3,
73                    value: "C".into(),
74                };
75                #[rustfmt::skip] // let-else not supported yet
76                let Ok(data1) = data1.try_to_vec() else {
77                    return Err(Error::SerializeError);
78                };
79                #[rustfmt::skip] // let-else not supported yet
80                let Ok(data2) = data2.try_to_vec() else {
81                    return Err(Error::SerializeError);
82                };
83                #[rustfmt::skip] // let-else not supported yet
84                let Ok(data3) = data3.try_to_vec() else {
85                    return Err(Error::SerializeError);
86                };
87                Ok(vec![data1, data2, data3])
88            }
89
90            #[test]
91            fn basic_operations_test() {
92                let db = <$type>::default();
93                let first_collection: $type2 = db.create_collection("first");
94                let data = get_data().unwrap();
95                // PUT & GET Operations
96                // PUT
97                let result = first_collection.put("a", data[0].clone());
98                assert!(result.is_ok());
99                let result = first_collection.put("b", data[1].clone());
100                assert!(result.is_ok());
101                let result = first_collection.put("c", data[2].clone());
102                assert!(result.is_ok());
103                // GET
104                let result = first_collection.get("a");
105                assert!(result.is_ok());
106                assert_eq!(result.unwrap(), data[0]);
107                let result = first_collection.get("b");
108                assert!(result.is_ok());
109                assert_eq!(result.unwrap(), data[1]);
110                let result = first_collection.get("c");
111                assert!(result.is_ok());
112                assert_eq!(result.unwrap(), data[2]);
113                // DEL
114                let result = first_collection.del("a");
115                assert!(result.is_ok());
116                let result = first_collection.del("b");
117                assert!(result.is_ok());
118                let result = first_collection.del("c");
119                assert!(result.is_ok());
120                // GET OF DELETED ENTRIES
121                let result = first_collection.get("a");
122                assert!(result.is_err());
123                let result = first_collection.get("b");
124                assert!(result.is_err());
125                let result = first_collection.get("c");
126                assert!(result.is_err());
127            }
128
129            #[test]
130            fn partitions_test() {
131                let db = <$type>::default();
132                let first_collection: $type2 = db.create_collection("first");
133                let second_collection: $type2 = db.create_collection("second");
134                let data = get_data().unwrap();
135                // PUT UNIQUE ENTRIES IN EACH PARTITION
136                let result = first_collection.put("a", data[0].to_owned());
137                assert!(result.is_ok());
138                let result = second_collection.put("b", data[1].to_owned());
139                assert!(result.is_ok());
140                // NO EXIST IDIVIDUALITY
141                let result = first_collection.get("b");
142                assert_eq!(result.unwrap(), data[1]);
143                let result = second_collection.get("a");
144                assert_eq!(result.unwrap(), data[0]);
145            }
146
147            #[allow(dead_code)]
148            fn build_state(collection: &$type2) {
149                let data = get_data().unwrap();
150                let result = collection.put("a", data[0].to_owned());
151                assert!(result.is_ok());
152                let result = collection.put("b", data[1].to_owned());
153                assert!(result.is_ok());
154                let result = collection.put("c", data[2].to_owned());
155                assert!(result.is_ok());
156            }
157
158            #[allow(dead_code)]
159            fn build_initial_data() -> (Vec<&'static str>, Vec<Vec<u8>>) {
160                let keys = vec!["a", "b", "c"];
161                let data = get_data().unwrap();
162                let values = vec![data[0].to_owned(), data[1].to_owned(), data[2].to_owned()];
163                (keys, values)
164            }
165
166            #[test]
167            fn iterator_test() {
168                let db = <$type>::default();
169                let first_collection: $type2 = db.create_collection("first");
170                build_state(&first_collection);
171                // ITER TEST
172                let mut iter = first_collection.iter(false, "first".to_string());
173                assert!(iter.next().is_none());
174                let mut iter = first_collection.iter(false, "".to_string());
175                let (keys, data) = build_initial_data();
176                for i in 0..3 {
177                    let (key, val) = iter.next().unwrap();
178                    assert_eq!(keys[i], key);
179                    assert_eq!(data[i], val);
180                }
181                assert!(iter.next().is_none());
182            }
183
184            #[test]
185            fn rev_iterator_test() {
186                let db = <$type>::default();
187                let first_collection: $type2 = db.create_collection("first");
188                build_state(&first_collection);
189                // ITER TEST
190                let mut iter = first_collection.iter(true, "first".to_string());
191                assert!(iter.next().is_none());
192                let mut iter = first_collection.iter(true, "".to_string());
193                let (keys, data) = build_initial_data();
194                for i in (0..3).rev() {
195                    let (key, val) = iter.next().unwrap();
196                    assert_eq!(keys[i], key);
197                    assert_eq!(data[i], val);
198                }
199                assert!(iter.next().is_none());
200            }
201        }
202    };
203}