persistent_keystore_rs/
lib.rs

1use std::path::{Path, PathBuf};
2use std::fs::File;
3use std::io::SeekFrom;
4use std::time::{SystemTime, Duration};
5use std::collections::HashMap;
6use std::io::prelude::*;
7use std::sync::{Arc, Mutex};
8use std::thread::sleep;
9use std::fs::OpenOptions;
10use lz4_flex::{compress_prepend_size, decompress_size_prepended};
11use tracing::{debug, error, info, trace};
12
13mod structs;
14pub mod errors;
15pub mod prelude;
16pub use structs::*;
17#[cfg(feature = "mocks")]
18pub use prelude::MockDatabaseClient;
19use errors::*;
20use prelude::*;
21use std::thread::JoinHandle;
22
23struct Saver {
24    handle: Option<JoinHandle<()>>,
25    killer: std::sync::mpsc::SyncSender<()>,
26}
27
28impl Drop for Saver {
29    fn drop(&mut self) {
30        self.killer.send(()).unwrap();
31        if let Some(h) = self.handle.take() {
32            h.join().unwrap();
33        }
34    }
35}
36
37/// Thread-safe, optionally persistent client for interacting with a keystore database
38#[derive(Clone)]
39pub struct Client {
40    database: Arc<Mutex<Database>>,
41    raw_file: Arc<Mutex<PathBuf>>,
42    handle: Arc<Option<Saver>>,
43}
44
45fn open_file<P: AsRef<Path> + Clone + std::fmt::Debug>(path: P) -> Result<File, std::io::Error> {
46    debug!("Opening file {:?}", path);
47    OpenOptions::new()
48        .write(true)
49        .read(true)
50        .create(false)
51        .truncate(false)
52        .append(false)
53        .open(path)
54}
55
56impl Client {
57    /// Creates a database at the supplied path
58    /// ```
59    /// # use persistent_keystore_rs::Client;
60    /// use std::path::Path;
61    /// let c = Client::new(Path::new("temp.db"), None);
62    /// # std::fs::remove_file("temp.db").unwrap();
63    /// ```
64    /// This database will not sync on its own and will need to be saved with 
65    /// ```
66    /// # use persistent_keystore_rs::Client;
67    /// # let mut c = Client::new(std::path::Path::new("temp2.db"), None).unwrap();
68    /// c.save();
69    /// # std::fs::remove_file("temp2.db").unwrap();
70    /// ```
71    /// 
72    /// To create a persistent database that will create a thread attached to the lifetime
73    /// of the client provide a duration
74    /// ```
75    /// # use persistent_keystore_rs::Client;
76    /// use std::path::Path;
77    /// use std::time::Duration;
78    /// let c = Client::new(Path::new("temp3.db"), Some(Duration::from_millis(30)));
79    /// # drop(c);
80    /// # std::fs::remove_file("temp3.db").unwrap();
81    /// ```
82    /// This thread will prune (remove stale entries) and save the database
83    /// every duration
84    pub fn new<P: AsRef<Path> + Clone + std::fmt::Debug>(path: P, sync_interval: Option<Duration>) -> Result<Box<dyn DatabaseClient>, DatabaseError> {
85        info!("Creating Client with database at {:?}", path);
86        if path.as_ref().exists() {
87            error!("Database exists, cannot create: {:?}", path);
88            return Err(DatabaseError::DatabaseExistsError)
89        };
90
91        let mut database = Database::default();
92        
93        if let Some(d) = sync_interval {
94            debug!("Setting sync interval to {:?}", d);
95            database.set_sync_duration(d);
96        };
97
98        let mut client = Self{
99            database: Arc::new(Mutex::new(database)),
100            raw_file: Arc::new(Mutex::new(PathBuf::from(path.as_ref()))),
101            handle: Arc::new(None),
102        };
103
104        if let Some(d) = sync_interval {
105            let mut c = client.clone();
106            let (tx, rx) = std::sync::mpsc::sync_channel(0);
107            let h = std::thread::spawn( move || loop {
108                    if let Ok(_) = rx.try_recv() {
109                        trace!("Breaking");
110                        break
111                    };
112
113                    trace!("Sleeping for {:?}", d);
114                    sleep(d);
115
116                    trace!("Pruning database");
117                    c.prune().unwrap();
118                    debug!("Database pruned");
119                    
120                    trace!("Saving database");
121                    c.save().unwrap();
122                    debug!("Database saved");
123                }
124            );
125            client.handle = Arc::new(Some(Saver{
126                handle: Some(h),
127                killer: tx,
128            }));
129        };
130
131        client.save()?;
132        trace!("Returning Client");
133        Ok(Box::new(client))
134    }
135
136    /// Opens an existing database at the supplied path
137    /// ```
138    /// # use persistent_keystore_rs::Client;
139    /// use std::path::Path;
140    /// # let c = Client::new(Path::new("existing.db"), None);
141    /// # drop(c);
142    /// let c = Client::open(Path::new("existing.db"));
143    /// # std::fs::remove_file("existing.db").unwrap();
144    /// ```
145    /// This database will resume the sync settings that were provided when
146    /// the database was created.
147    pub fn open<P: AsRef<Path> + Clone + std::fmt::Debug>(path: P) -> Result<Box<dyn DatabaseClient>, DatabaseError> {
148        info!("Opening Client with database at {:?}", path);
149        if !path.as_ref().exists() {
150            error!("Database does not exist exists, cannot open: {:?}", path);
151            return Err(DatabaseError::DatabaseDoesNotExist(path.as_ref().to_str().unwrap().to_string()))
152        } ;
153
154        let mut f = open_file(&path)?;
155        let mut compressed: Vec<u8> = Vec::new();
156        f.read_to_end(&mut compressed)?;
157        let uncompressed = decompress_size_prepended(&compressed)?;
158        let database: Database = bincode::deserialize(&uncompressed)?;
159        let sync_interval = database.sync_interval.clone();
160
161        let mut client = Self{
162            database: Arc::new(Mutex::new(database)),
163            raw_file: Arc::new(Mutex::new(PathBuf::from(path.as_ref()))),
164            handle: Arc::new(None),
165        };
166
167        if let Some(duration) = sync_interval {
168            let mut c = client.clone();
169            let (tx, rx) = std::sync::mpsc::sync_channel(0);
170            let h = std::thread::spawn( move || loop {
171                    if let Ok(_) = rx.try_recv() {
172                        trace!("Breaking");
173                        break
174                    };
175    
176                    trace!("Sleeping for {:?}", duration);
177                    sleep(duration);
178                    
179                    trace!("Pruning database");
180                    c.prune().unwrap();
181                    debug!("Database pruned");
182                    
183                    trace!("Saving database");
184                    c.save().unwrap();
185                    debug!("Database saved");
186                }
187            );
188    
189            client.handle = Arc::new(Some(Saver{
190                handle: Some(h),
191                killer: tx,
192            }));
193        };
194        
195
196        trace!("Returning Client");
197
198        Ok(Box::new(client))
199    }
200}
201
202impl DatabaseClient for Client {
203    /// Removes stale entries as defined by the expiration value per table
204    /// and saves the database to disk; using lz4 compression
205    /// ```
206    /// # use persistent_keystore_rs::Client;
207    /// use std::path::Path;
208    /// let c = Client::new(Path::new("saved.db"), None);
209    /// # std::fs::remove_file("saved.db").unwrap();
210    /// ```
211    /// This database will not sync on its own and will need to be saved with 
212    /// ```
213    /// # use persistent_keystore_rs::Client;
214    /// # let mut c = Client::new(std::path::Path::new("saved2.db"), None).unwrap();
215    /// c.save();
216    /// # std::fs::remove_file("saved2.db").unwrap();
217    fn save(&mut self) -> Result<(), DatabaseError> {
218        trace!("Saving database");
219        if let Ok(database) = self.database.lock() {
220            if let Ok(raw_file) = self.raw_file.lock() {
221                debug!("Saving database {:?}", raw_file);
222                let mut f = OpenOptions::new()
223                    .write(true)
224                    .read(true)
225                    .create(true)
226                    .truncate(true)
227                    .append(false)
228                    .open(raw_file.as_path())?;
229                let output = bincode::serialize(&database.clone())?;
230                let compressed = compress_prepend_size(&output);
231                f.seek(SeekFrom::Start(0))?;
232                f.write_all(&compressed)?;
233                f.flush()?;
234                f.sync_all()?;
235                drop(f);
236                return Ok(())
237
238            } else {
239                error!("Unable to get file mutex");
240            };
241        };
242        error!("Unable to get database lock");
243        Err(DatabaseError::UnableToGetLock)
244    }
245
246    /// Creates a table within the database of the associated client
247    /// ```
248    /// use persistent_keystore_rs::{Client, Table, FieldType};
249    /// use persistent_keystore_rs::prelude::*;
250    /// use std::time::Duration;
251    /// # use std::path::Path;
252    /// let mut c = Client::new(Path::new("createtable.db"), None).unwrap();
253    /// let table = Table::new()
254    ///     .name(String::from("MyTable"))
255    ///     .primary_field(FieldType::String).unwrap()
256    ///     .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
257    ///     .add_expiration(Duration::from_secs(2592000))
258    ///     .build().unwrap();
259    /// c.create_table(table).unwrap();
260    /// # std::fs::remove_file("createtable.db").unwrap();
261    /// ```
262    fn create_table(&mut self, table: Table) -> Result<(), DatabaseError> {
263        trace!("Creating table {}", table.name);
264        if let Ok(mut database) = self.database.lock() {
265            match database.get_table(&table.name.clone()) {
266                Ok(_) => {
267                    error!("Table {} exists", table.name);
268                    return Err(DatabaseError::TableExists(table.name))
269                },
270                Err(_) => {
271                    debug!("Creating table {}", table.name);
272                    return database.create_table(table)
273                },
274            };
275        };
276        error!("Unable to get database lock");
277        Err(DatabaseError::UnableToGetLock)
278    }
279
280    /// Lists tables within the database of the associated client
281    /// ```
282    /// # use persistent_keystore_rs::{Client, Table, FieldType};
283    /// # use std::time::Duration;
284    /// # use std::path::Path;
285    /// let mut c = Client::new(Path::new("listtable.db"), None).unwrap();
286    /// # let table = Table::new()
287    /// #    .name(String::from("MyTable"))
288    /// #    .primary_field(FieldType::String).unwrap()
289    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
290    /// #    .add_expiration(Duration::from_secs(2592000))
291    /// #    .build().unwrap();
292    /// # c.create_table(table).unwrap();
293    /// let tables = c.list_tables().unwrap();
294    /// assert_eq!(tables.len(), 1);
295    /// assert_eq!(tables[0], String::from("MyTable"));
296    /// # std::fs::remove_file("listtable.db").unwrap();
297    /// ```
298    fn list_tables(&mut self) -> Result<Vec<String>, DatabaseError> {
299        trace!("Listing Tables");
300        if let Ok(mut database) = self.database.lock() {
301            let tables = database.list_tables();
302            debug!("Listed {} tables", tables.len());
303            return Ok(tables)
304        };
305        error!("Unable to get database lock");
306        Err(DatabaseError::UnableToGetLock)
307    }
308
309    /// Drops the specified table from within the database of the associated client
310    /// ```
311    /// # use persistent_keystore_rs::{Client, Table, FieldType};
312    /// # use std::time::Duration;
313    /// # use std::path::Path;
314    /// let mut c = Client::new(Path::new("droptable.db"), None).unwrap();
315    /// # let table = Table::new()
316    /// #    .name(String::from("MyTable"))
317    /// #    .primary_field(FieldType::String).unwrap()
318    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
319    /// #    .add_expiration(Duration::from_secs(2592000))
320    /// #    .build().unwrap();
321    /// # c.create_table(table).unwrap();
322    /// let tables = c.list_tables().unwrap();
323    /// assert_eq!(tables.len(), 1);
324    /// assert_eq!(tables[0], String::from("MyTable"));
325    /// c.drop_table(&String::from("MyTable")).unwrap();
326    /// let current_tables = c.list_tables().unwrap();
327    /// assert_eq!(current_tables.len(), 0);
328    /// # std::fs::remove_file("droptable.db").unwrap();
329    /// ```
330    fn drop_table(&mut self, table: &String) -> Result<(), DatabaseError> {
331        trace!("Dropping table {}", table);
332        if let Ok(mut database) = self.database.lock() {
333            debug!("Dropping table {}", table);
334            return database.drop_table(table)
335        };
336        error!("Unable to get database lock");
337        Err(DatabaseError::UnableToGetLock)
338    }
339
340    /// Inserts the provided entry into the specified table within the database of the associated client.
341    /// If an entry with the same primary key exists, an DatabaseError::EntryExists is returned
342    /// ```
343    /// # use persistent_keystore_rs::{Client, Table, FieldType};
344    /// use persistent_keystore_rs::{Entry, Field};
345    /// # use std::time::Duration;
346    /// # use std::path::Path;
347    /// use std::time::SystemTime;
348    /// let mut c = Client::new(Path::new("insertentry.db"), None).unwrap();
349    /// # let table = Table::new()
350    /// #    .name(String::from("MyTable"))
351    /// #    .primary_field(FieldType::String).unwrap()
352    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
353    /// #    .add_expiration(Duration::from_secs(2592000))
354    /// #    .build().unwrap();
355    /// # c.create_table(table).unwrap();
356    /// let entry = Entry::new()
357    ///     .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
358    ///     .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
359    ///     .build().unwrap();
360    /// c.insert("MyTable".to_string(), entry).unwrap();
361    /// # std::fs::remove_file("insertentry.db").unwrap();
362    /// ```
363    fn insert(&mut self, table: String, entry: Entry) -> Result<(), DatabaseError> {
364        trace!("Inserting entry into table {}: {}", table, entry);
365        if let Ok(mut database) = self.database.lock() {
366            match database.get_table(&table) {
367                Ok(t) => {
368                    debug!("Inserting entry into table {}", table);
369                    return t.insert(entry)
370                },
371                Err(_) => {
372                    error!("Table {} does not exist", table);
373                    return Err(DatabaseError::TableDoesNotExist(table))
374                }
375            }
376        };
377        error!("Unable to get database lock");
378        Err(DatabaseError::UnableToGetLock)
379    }
380
381    /// Inserts the provided entry into the specified table within the database of the associated client.
382    /// If an entry with the same primary key exists, the entry is updated.
383    /// ```
384    /// # use persistent_keystore_rs::{Client, Table, FieldType};
385    /// use persistent_keystore_rs::{Entry, Field};
386    /// # use std::time::Duration;
387    /// # use std::path::Path;
388    /// use std::time::SystemTime;
389    /// let mut c = Client::new(Path::new("insertorupdateentry.db"), None).unwrap();
390    /// # let table = Table::new()
391    /// #    .name(String::from("MyTable"))
392    /// #    .primary_field(FieldType::String).unwrap()
393    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
394    /// #    .add_expiration(Duration::from_secs(2592000))
395    /// #    .build().unwrap();
396    /// # c.create_table(table).unwrap();
397    /// let entry = Entry::new()
398    ///     .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
399    ///     .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
400    ///     .build().unwrap();
401    /// c.insert("MyTable".to_string(), entry.clone()).unwrap();
402    /// c.insert_or_update("MyTable".to_string(), entry).unwrap();
403    /// # std::fs::remove_file("insertorupdateentry.db").unwrap();
404    /// ```
405    fn insert_or_update(&mut self, table: String, entry: Entry) -> Result<(), DatabaseError> {
406        trace!("Inserting or updating entry into table {}: {}", table, entry);
407        if let Ok(mut database) = self.database.lock() {
408            match database.get_table(&table) {
409                Ok(t) => {
410                    debug!("Inserting entry into table {}", table);
411                    return t.insert_or_update(entry)
412                },
413                Err(_) => {
414                    error!("Table {} does not exist", table);
415                    return Err(DatabaseError::TableDoesNotExist(table))
416                },
417            }
418        };
419        error!("Unable to get database lock");
420        Err(DatabaseError::UnableToGetLock)
421    }
422
423    /// Updates an existing entry in the specified table within the database of the associated client.
424    /// If an entry does not exist, DatabaseError::EntryDoesNotExists is returned
425    /// ```
426    /// # use persistent_keystore_rs::{Client, Table, FieldType};
427    /// use persistent_keystore_rs::{Entry, Field};
428    /// # use std::time::Duration;
429    /// # use std::path::Path;
430    /// use std::time::SystemTime;
431    /// let mut c = Client::new(Path::new("updateentry.db"), None).unwrap();
432    /// # let table = Table::new()
433    /// #    .name(String::from("MyTable"))
434    /// #    .primary_field(FieldType::String).unwrap()
435    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
436    /// #    .add_expiration(Duration::from_secs(2592000))
437    /// #    .build().unwrap();
438    /// # c.create_table(table).unwrap();
439    /// let entry = Entry::new()
440    ///     .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
441    ///     .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
442    ///     .build().unwrap();
443    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
444    /// c.update("MyTable".to_string(), entry).unwrap();
445    /// # std::fs::remove_file("updateentry.db").unwrap();
446    /// ```
447    fn update(&mut self, table: String, entry: Entry) -> Result<(), DatabaseError> {
448        trace!("Updating entry into table {}: {}", table, entry);
449        if let Ok(mut database) = self.database.lock() {
450            match database.get_table(&table) {
451                Ok(t) => {
452                    debug!("Updating entry {} in table {}", entry.primary_field, table);
453                    return t.update(entry)
454                },
455                Err(_) => {
456                    error!("Table {} does not exist", table);
457                    return Err(DatabaseError::TableDoesNotExist(table))
458                }
459            }
460        };
461        error!("Unable to get database lock");
462        Err(DatabaseError::UnableToGetLock)
463    }
464
465    /// Get an existing entry from the specified table within the database of the associated client.
466    /// If an entry does not exist, DatabaseError::EntryDoesNotExists is returned
467    /// ```
468    /// # use persistent_keystore_rs::{Client, Table, FieldType, Entry};
469    /// use persistent_keystore_rs::Field;
470    /// # use std::time::Duration;
471    /// # use std::path::Path;
472    /// # use std::time::SystemTime;
473    /// let mut c = Client::new(Path::new("getentry.db"), None).unwrap();
474    /// # let table = Table::new()
475    /// #    .name(String::from("MyTable"))
476    /// #    .primary_field(FieldType::String).unwrap()
477    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
478    /// #    .add_expiration(Duration::from_secs(2592000))
479    /// #    .build().unwrap();
480    /// # c.create_table(table).unwrap();
481    /// # let entry = Entry::new()
482    /// #    .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
483    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
484    /// #    .build().unwrap();
485    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
486    /// let e = c.get("MyTable".to_string(), Field::String("MyFirstEntry".to_string())).unwrap();
487    /// # std::fs::remove_file("getentry.db").unwrap();
488    /// ```
489    fn get(&mut self, table: String, primary_field: Field) -> Result<Entry, DatabaseError> {
490        trace!("Getting entry {} from table {}", primary_field, table);
491        if let Ok(mut database) = self.database.lock() {
492            match database.get_table(&table) {
493                Ok(t) => {
494                    debug!("Getting entry {} from table {}", primary_field, table);
495                    let item = t.get(&primary_field)?;
496                    return Ok(item.clone());
497                },
498                Err(_) => {
499                    error!("Table {} does not exist", table);
500                    return Err(DatabaseError::TableDoesNotExist(table))
501                }
502            }
503        };
504        error!("Unable to get database lock");
505        Err(DatabaseError::UnableToGetLock)
506    }
507
508    /// Delete an existing entry from the specified table within the database of the associated client.
509    /// If an entry does not exist, DatabaseError::EntryDoesNotExists is returned
510    /// ```
511    /// # use persistent_keystore_rs::{Client, Table, FieldType, Entry};
512    /// use persistent_keystore_rs::Field;
513    /// # use std::time::Duration;
514    /// # use std::path::Path;
515    /// # use std::time::SystemTime;
516    /// let mut c = Client::new(Path::new("delete.db"), None).unwrap();
517    /// # let table = Table::new()
518    /// #    .name(String::from("MyTable"))
519    /// #    .primary_field(FieldType::String).unwrap()
520    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
521    /// #    .add_expiration(Duration::from_secs(2592000))
522    /// #    .build().unwrap();
523    /// # c.create_table(table).unwrap();
524    /// # let entry = Entry::new()
525    /// #    .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
526    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
527    /// #    .build().unwrap();
528    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
529    /// c.delete("MyTable".to_string(), Field::String("MyFirstEntry".to_string())).unwrap();
530    /// # std::fs::remove_file("delete.db").unwrap();
531    /// ```
532    fn delete(&mut self, table: String, primary_field: Field) -> Result<(), DatabaseError> {
533        trace!("Deleting entry {} from table {}", primary_field, table);
534        if let Ok(mut database) = self.database.lock() {
535            match database.get_table(&table) {
536                Ok(t) => {
537                    debug!("Deleting entry {} from table {}", primary_field, table);
538                    return t.delete(primary_field)
539                },
540                Err(_) => {
541                    error!("Table {} does not exist", table);
542                    return Err(DatabaseError::TableDoesNotExist(table))
543                },
544            }
545        };
546        error!("Unable to get database lock");
547        Err(DatabaseError::UnableToGetLock)
548    }
549
550    /// Delete all entries matching the supplied criteria.
551    /// ```
552    /// # use persistent_keystore_rs::{Client, Table, FieldType, Entry};
553    /// use persistent_keystore_rs::Field;
554    /// use std::collections::HashMap;
555    /// # use std::time::Duration;
556    /// # use std::path::Path;
557    /// # use std::time::SystemTime;
558    /// let mut c = Client::new(Path::new("deletemany.db"), None).unwrap();
559    /// # let table = Table::new()
560    /// #    .name(String::from("MyTable"))
561    /// #    .primary_field(FieldType::String).unwrap()
562    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
563    /// #    .add_field(String::from("OptionalField"), FieldType::String).unwrap()
564    /// #    .add_expiration(Duration::from_secs(2592000))
565    /// #    .build().unwrap();
566    /// # c.create_table(table).unwrap();
567    /// # let entry = Entry::new()
568    /// #    .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
569    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
570    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
571    /// #    .build().unwrap();
572    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
573    /// # let entry2 = Entry::new()
574    /// #    .set_primary_field(Field::String("MySecondEntry".to_string())).unwrap()
575    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
576    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
577    /// #    .build().unwrap();
578    /// # c.insert("MyTable".to_string(), entry2.clone()).unwrap();
579    /// # let entry3 = Entry::new()
580    /// #    .set_primary_field(Field::String("MyThirdEntry".to_string())).unwrap()
581    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
582    /// #    .add_field("OptionalField".to_string(), Field::String("MyOtherTestingField".to_string())).unwrap()
583    /// #    .build().unwrap();
584    /// # c.insert("MyTable".to_string(), entry3.clone()).unwrap();
585    /// let mut criteria: HashMap<String, Field> = HashMap::new();
586    /// criteria.insert("OptionalField".to_string(), Field::String("MyTestingField".to_string()));
587    /// c.delete_many("MyTable".to_string(), criteria).unwrap();
588    /// # assert_eq!(c.scan("MyTable".to_string()).unwrap().len(), 1);
589    /// # std::fs::remove_file("deletemany.db").unwrap();
590    /// ```
591    fn delete_many(&mut self, table: String, criteria: HashMap<String, Field>) -> Result<u64, DatabaseError> {
592        trace!("Deleting many from table {}", table);
593        if let Ok(mut database) = self.database.lock() {
594            match database.get_table(&table) {
595                Ok(t) => {
596                    let items = t.scan()?;
597                    let mut deleted = 0;
598                    'L:
599                    for i in items {
600                        for (k, v) in &criteria {
601                            match &i.fields.get_key_value(k) {
602                                Some((_, value)) => {
603                                    if v != *value {
604                                        trace!("{} does not meet criteria", i.primary_field);
605                                        continue 'L;
606                                    }
607                                },
608                                None => {
609                                    trace!("{} does not meet criteria", i.primary_field);
610                                    continue 'L
611                                },
612                            };
613                            
614                        };
615                        debug!("Deleting entry {} from table {}", i.primary_field, table);
616                        t.delete(i.primary_field)?;
617                        deleted+=1;
618                    };
619                    return Ok(deleted)
620                },
621                Err(_) => {
622                    error!("Table {} does not exist", table);
623                    return Err(DatabaseError::TableDoesNotExist(table))
624                },
625            };
626        };
627        error!("Unable to get database lock");
628        Err(DatabaseError::UnableToGetLock)
629    }
630
631    /// Returns all entries from the specified table within the database of the associated client.
632    /// If no entries exist, will return an empty vec
633    /// ```
634    /// # use persistent_keystore_rs::{Client, Table, FieldType, Entry, Field};
635    /// # use std::time::Duration;
636    /// # use std::path::Path;
637    /// # use std::time::SystemTime;
638    /// let mut c = Client::new(Path::new("scan.db"), None).unwrap();
639    /// # let table = Table::new()
640    /// #    .name(String::from("MyTable"))
641    /// #    .primary_field(FieldType::String).unwrap()
642    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
643    /// #    .add_field(String::from("OptionalField"), FieldType::String).unwrap()
644    /// #    .add_expiration(Duration::from_secs(2592000))
645    /// #    .build().unwrap();
646    /// # c.create_table(table).unwrap();
647    /// # let entry = Entry::new()
648    /// #    .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
649    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
650    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
651    /// #    .build().unwrap();
652    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
653    /// # let entry2 = Entry::new()
654    /// #    .set_primary_field(Field::String("MySecondEntry".to_string())).unwrap()
655    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
656    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
657    /// #    .build().unwrap();
658    /// # c.insert("MyTable".to_string(), entry2.clone()).unwrap();
659    /// # let entry3 = Entry::new()
660    /// #    .set_primary_field(Field::String("MyThirdEntry".to_string())).unwrap()
661    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
662    /// #    .add_field("OptionalField".to_string(), Field::String("MyOtherTestingField".to_string())).unwrap()
663    /// #    .build().unwrap();
664    /// # c.insert("MyTable".to_string(), entry3.clone()).unwrap();
665    /// let results = c.scan("MyTable".to_string()).unwrap();
666    /// # assert_eq!(c.scan("MyTable".to_string()).unwrap().len(), 3);
667    /// # std::fs::remove_file("scan.db").unwrap();
668    /// ```
669    fn scan(&mut self, table: String) -> Result<Vec<Entry>, DatabaseError> {
670        trace!("Scanning table {}", table);
671        if let Ok(mut database) = self.database.lock() {
672            match database.get_table(&table) {
673                Ok(t) => {
674                    debug!("Scanning table {}", table);
675                    return t.scan()
676                },
677                Err(_) => {
678                    error!("Table {} does not exist", table);
679                    return Err(DatabaseError::TableDoesNotExist(table))
680                },
681            };
682        };
683        error!("Unable to get database lock");
684        Err(DatabaseError::UnableToGetLock)
685    }
686
687    /// Query for entries within a specified table meeting the supplied criteria.
688    /// ```
689    /// # use persistent_keystore_rs::{Client, Table, FieldType, Entry};
690    /// use persistent_keystore_rs::Field;
691    /// use std::collections::HashMap;
692    /// # use std::time::Duration;
693    /// # use std::path::Path;
694    /// # use std::time::SystemTime;
695    /// let mut c = Client::new(Path::new("query.db"), None).unwrap();
696    /// # let table = Table::new()
697    /// #    .name(String::from("MyTable"))
698    /// #    .primary_field(FieldType::String).unwrap()
699    /// #    .add_field(String::from("TimeStamp"), FieldType::Date).unwrap()
700    /// #    .add_field(String::from("OptionalField"), FieldType::String).unwrap()
701    /// #    .add_expiration(Duration::from_secs(2592000))
702    /// #    .build().unwrap();
703    /// # c.create_table(table).unwrap();
704    /// # let entry = Entry::new()
705    /// #    .set_primary_field(Field::String("MyFirstEntry".to_string())).unwrap()
706    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
707    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
708    /// #    .build().unwrap();
709    /// # c.insert("MyTable".to_string(), entry.clone()).unwrap();
710    /// # let entry2 = Entry::new()
711    /// #    .set_primary_field(Field::String("MySecondEntry".to_string())).unwrap()
712    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
713    /// #    .add_field("OptionalField".to_string(), Field::String("MyTestingField".to_string())).unwrap()
714    /// #    .build().unwrap();
715    /// # c.insert("MyTable".to_string(), entry2.clone()).unwrap();
716    /// # let entry3 = Entry::new()
717    /// #    .set_primary_field(Field::String("MyThirdEntry".to_string())).unwrap()
718    /// #    .add_field("TimeStamp".to_string(), Field::Date(SystemTime::now())).unwrap()
719    /// #    .add_field("OptionalField".to_string(), Field::String("MyOtherTestingField".to_string())).unwrap()
720    /// #    .build().unwrap();
721    /// # c.insert("MyTable".to_string(), entry3.clone()).unwrap();
722    /// let mut criteria: HashMap<String, Field> = HashMap::new();
723    /// criteria.insert("OptionalField".to_string(), Field::String("MyTestingField".to_string()));
724    /// let results = c.query("MyTable".to_string(), criteria).unwrap();
725    /// # assert_eq!(results.len(), 2);
726    /// # std::fs::remove_file("query.db").unwrap();
727    /// ```
728    fn query(&mut self, table: String, criteria: HashMap<String, Field>) -> Result<Vec<Entry>, DatabaseError> {
729        trace!("Querying table {}", table);
730        if let Ok(mut database) = self.database.lock() {
731            match database.get_table(&table) {
732                Ok(t) => {
733                    let items = t.scan()?;
734                    let mut results = Vec::new();
735                    'L:
736                    for i in items {
737                        for (k, v) in &criteria {
738                            match &i.fields.get_key_value(k) {
739                                Some((_, value)) => {
740                                    if v != *value {
741                                        trace!("{} does not meet criteria", i.primary_field);
742                                        continue 'L;
743                                    }
744                                },
745                                None => {
746                                    trace!("{} does not meet criteria", i.primary_field);
747                                    continue 'L;
748                                },
749                            };
750                            
751                        };
752                        results.push(i.clone());
753                    };
754                    return Ok(results)
755                },
756                Err(_) => {
757                    error!("Table {} does not exist", table);
758                    return Err(DatabaseError::TableDoesNotExist(table))
759                },
760            };
761        };
762        error!("Unable to get database lock");
763        Err(DatabaseError::UnableToGetLock)
764    }
765
766    /// Removes entries that have expired by the specified TTL field in the table.
767    /// This is done automatically before saves if a sync_interval is provided.
768    /// 
769    /// ```
770    /// use persistent_keystore_rs::{Client, Table, FieldType, Entry};
771    /// # use std::thread::sleep;
772    /// use persistent_keystore_rs::Field;
773    /// use std::collections::HashMap;
774    /// # use std::time::Duration;
775    /// # use std::path::Path;
776    /// # use std::time::SystemTime;
777    /// let mut c = Client::new(Path::new("prune.db"), None).unwrap();
778    /// let table = Table::new()
779    ///     .name(String::from("MyTable"))
780    ///     .add_expiration(Duration::from_secs(1))
781    ///     .primary_field(FieldType::String).unwrap()
782    ///     .add_field("FirstKey".to_string(), FieldType::I64).unwrap()
783    ///     .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
784    ///     .build().unwrap();
785    ///
786    /// c.create_table(table).unwrap();
787    ///
788    /// let entry_first = Entry::new()
789    ///     .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
790    ///     .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
791    ///     .add_field("OptionalKey".to_string(), Field::String("My first entry".to_string())).unwrap()
792    ///     .build().unwrap();
793    ///
794    /// let result = c.insert("MyTable".to_string(), entry_first);
795    ///
796    /// if let Err(e) = result {
797    ///     panic!("No error expected, received {}", e)
798    /// } 
799    ///
800    /// let output = c.scan("MyTable".to_string()).unwrap();
801    ///
802    /// if output.len() != 1 {
803    ///     panic!("Expected scan results to be 1")
804    /// };
805    ///
806    /// sleep(Duration::from_secs(2));
807    /// c.prune().unwrap();
808    ///
809    /// let output = c.scan("MyTable".to_string()).unwrap();
810    /// if output.len() != 0 {
811    ///     panic!("Expected scan results to be 0")
812    /// };
813    /// # std::fs::remove_file("prune.db").unwrap();
814    /// ```
815    fn prune(&mut self) -> Result<(), DatabaseError> {
816        trace!("Pruning database");
817        if let Ok(mut database) = self.database.lock() {
818            let current_time = SystemTime::now();
819            for t in database.list_tables() {
820                if let Ok(table) = database.get_table(&t) {
821                    if let Some(expire_after) = table.expire_after {
822                        let items = table.scan()?;
823                        for item in items {
824                            if let Some(n) = item.last_timestamp {
825                                if let Ok(last_time) = current_time.duration_since(n) {
826                                    if last_time > expire_after {
827                                        debug!("Pruning item {}", item.clone());
828                                        table.delete(item.primary_field)?;
829                                    } else {
830                                        trace!("Not yet expired {}", item.clone());
831                                    }
832                                } 
833                            }
834                        }
835                    } else {
836                        debug!("No expire after setting for table {}", t);
837                    }
838                }
839            };
840            return Ok(())
841        };
842        error!("Unable to get database lock");
843        Err(DatabaseError::UnableToGetLock)
844    }
845}
846
847#[cfg(test)]
848mod tests {
849    use super::*;
850    use std::env::temp_dir;
851
852    fn create_client_table(name: String) -> (Box<dyn DatabaseClient>, TableBuilder) {
853        let mut temp_dir_path = temp_dir();
854        temp_dir_path.push(format!("{}.db", name));
855        if temp_dir_path.exists() {
856            std::fs::remove_file(temp_dir_path.clone().to_str().unwrap()).unwrap();
857        };
858
859        let c = Client::new(temp_dir_path, None).unwrap();
860        
861        let table = structs::Table::new()
862            .name(name);
863
864        (c, table)
865    }
866
867    #[test]
868    fn entry_missing_fields() {
869        let missing_fields_entry = structs::Entry::new()
870            .set_primary_field(Field::String("This entry should fail".to_string())).unwrap()
871            .build();
872        
873        if let Err(e) = missing_fields_entry {
874            match e {
875                DatabaseError::EntryMustContainFields => {},
876                _ => panic!("Expected EntryMustContainFields but not {}", e),
877            };
878        } else {
879            panic!("Expected error and did not receive one");
880        };
881    }
882
883    #[test]
884    fn entry_mismatched_primary_field_type() {
885        let (mut c, table_builder) = create_client_table("MismatchedPrimaryFieldType".to_string());
886        
887        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
888            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
889            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
890            .build().unwrap();
891
892        c.create_table(table).unwrap();
893
894        let mismatched_primary_field_type = structs::Entry::new()
895            .set_primary_field(Field::I64(123123)).unwrap()
896            .add_field("FirstKey".to_string(), Field::String("testing".to_string())).unwrap()
897            .build().unwrap();
898
899        let result = c.insert("MismatchedPrimaryFieldType".to_string(), mismatched_primary_field_type);
900
901        if let Err(e) = result {
902            match e {
903                DatabaseError::MismatchedFieldType => {},
904                _ => panic!("Expected MismatchedField type, not {}", e),
905            };
906        } else {
907            panic!("Expected MismatchedFieldType error but received none");
908        };
909    }
910
911    #[test]
912    fn entry_mismatched_secondary_field_type() {
913        let (mut c, table_builder) = create_client_table("MismatchedSecondaryFieldType".to_string());
914        
915        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
916            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
917            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
918            .build().unwrap();
919
920        c.create_table(table).unwrap();
921
922        let mismatched_optional_field = structs::Entry::new()
923            .set_primary_field(Field::String("This should also fail".to_string())).unwrap()
924            .add_field("FirstKey".to_string(), Field::String("Should fail".to_string())).unwrap()
925            .build().unwrap();
926
927        let result = c.insert("MismatchedSecondaryFieldType".to_string(), mismatched_optional_field);
928
929        if let Err(e) = result {
930            match e {
931                DatabaseError::MismatchedFieldType => {},
932                _ => panic!("Expected MismatchedField type, not {}", e),
933            };
934        } else {
935            panic!("Expected MismatchedFieldType error but received none");
936        };
937    }
938
939    #[test]
940    fn entry_extra_undefined_field() {
941        let (mut c, table_builder) = create_client_table("EntryExtraUndefiniedField".to_string());
942        
943        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
944            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
945            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
946            .build().unwrap();
947
948        c.create_table(table).unwrap();
949
950        let extra_field = structs::Entry::new()
951            .set_primary_field(Field::String("This should also fail".to_string())).unwrap()
952            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
953            .add_field("OptionalKey".to_string(), Field::String("My second field".to_string())).unwrap()
954            .add_field("ExtraField".to_string(), Field::String("ExtraField".to_string())).unwrap()
955            .build().unwrap();
956
957        let result = c.insert("EntryExtraUndefiniedField".to_string(), extra_field);
958
959        if let Err(e) = result {
960            match e {
961                DatabaseError::UnsupportedField(_) => {},
962                _ => panic!("Expected UnsupportedField, got {}", e),
963            };
964        } else {
965            panic!("Expected UnsupportedField, got none")
966        }
967    }
968
969    #[test]
970    fn entry_table_does_not_exist() {
971        let (mut c, table_builder) = create_client_table("EntryTableDoesNotExist".to_string());
972        
973        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
974            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
975            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
976            .build().unwrap();
977
978        c.create_table(table).unwrap();
979
980        let extra_field = structs::Entry::new()
981            .set_primary_field(Field::String("This should also fail".to_string())).unwrap()
982            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
983            .add_field("OptionalKey".to_string(), Field::String("My second field".to_string())).unwrap()
984            .build().unwrap();
985
986        let result = c.insert("EntryTableDoesNotExist2".to_string(), extra_field);
987
988        if let Err(e) = result {
989            match e {
990                DatabaseError::TableDoesNotExist(_) =>  {},
991                _ => panic!("Expected TableDoesNotExist, got {}", e),
992            };
993        } else {
994            panic!("Expected TableDoesNotExist, got none")
995        }
996    }
997
998    #[test]
999    fn entry_success_without_optional() {
1000        let (mut c, table_builder) = create_client_table("EntrySuccessWithoutOptional".to_string());
1001        
1002        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1003            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1004            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1005            .build().unwrap();
1006
1007        c.create_table(table).unwrap();
1008
1009        let extra_field = structs::Entry::new()
1010            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1011            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1012            .build().unwrap();
1013
1014        let result = c.insert("EntrySuccessWithoutOptional".to_string(), extra_field);
1015
1016        if let Err(e) = result {
1017            panic!("No error expected, received {}", e)
1018        } 
1019    }
1020
1021    #[test]
1022    fn entry_success_with_optional() {
1023        let (mut c, table_builder) = create_client_table("EntrySuccessWithOptional".to_string());
1024        
1025        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1026            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1027            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1028            .build().unwrap();
1029
1030        c.create_table(table).unwrap();
1031
1032        let extra_field = structs::Entry::new()
1033            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1034            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1035            .add_field("OptionalKey".to_string(), Field::String("My second field".to_string())).unwrap()
1036            .build().unwrap();
1037
1038        let result = c.insert("EntrySuccessWithOptional".to_string(), extra_field);
1039
1040        if let Err(e) = result {
1041            panic!("No error expected, received {}", e)
1042        } 
1043    }
1044
1045    #[test]
1046    fn entry_update_success() {
1047        let (mut c, table_builder) = create_client_table("EntryUpdateSuccess".to_string());
1048        
1049        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1050            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1051            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1052            .build().unwrap();
1053
1054        c.create_table(table).unwrap();
1055
1056        let entry_first = structs::Entry::new()
1057            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1058            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1059            .add_field("OptionalKey".to_string(), Field::String("My first entry".to_string())).unwrap()
1060            .build().unwrap();
1061
1062        let result = c.insert("EntryUpdateSuccess".to_string(), entry_first);
1063
1064        if let Err(e) = result {
1065            panic!("No error expected, received {}", e)
1066        } 
1067
1068        let entry_second = structs::Entry::new()
1069            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1070            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1071            .add_field("OptionalKey".to_string(), Field::String("My second entry".to_string())).unwrap()
1072            .build().unwrap();
1073
1074        let result = c.update("EntryUpdateSuccess".to_string(), entry_second.clone());
1075
1076        if let Err(e) = result {
1077            panic!("No error expected, received {}", e)
1078        }
1079
1080        let curent_entry = c.get("EntryUpdateSuccess".to_string(), Field::String("This should Succeed".to_string())).unwrap();
1081        assert!(curent_entry.primary_field==entry_second.primary_field);
1082        assert!(curent_entry.fields==entry_second.fields);
1083    }
1084
1085    #[test]
1086    fn entry_failure_second_insert() {
1087        let (mut c, table_builder) = create_client_table("SecondInsertFailure".to_string());
1088        
1089        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1090            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1091            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1092            .build().unwrap();
1093
1094        c.create_table(table).unwrap();
1095
1096        let entry_first = structs::Entry::new()
1097            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1098            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1099            .add_field("OptionalKey".to_string(), Field::String("My first entry".to_string())).unwrap()
1100            .build().unwrap();
1101
1102        let result = c.insert("SecondInsertFailure".to_string(), entry_first);
1103
1104        if let Err(e) = result {
1105            panic!("No error expected, received {}", e)
1106        } 
1107
1108        let entry_second = structs::Entry::new()
1109            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1110            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1111            .add_field("OptionalKey".to_string(), Field::String("My second entry".to_string())).unwrap()
1112            .build().unwrap();
1113
1114        let result = c.insert("SecondInsertFailure".to_string(), entry_second);
1115
1116        if let Err(e) = result {
1117            match e {
1118                DatabaseError::EntryExists => {},
1119                _ => panic!("Expected EntryExists, got {}", e),
1120            };
1121        } else {
1122            panic!("Expected EntryExists, got none")
1123        }
1124    }
1125
1126    #[test]
1127    fn database_open_close() {
1128        let (mut c, table_builder) = create_client_table("OpenSaveCloseOpen".to_string());
1129        
1130        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1131            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1132            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1133            .build().unwrap();
1134
1135        c.create_table(table).unwrap();
1136
1137        let entry_first = structs::Entry::new()
1138            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1139            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1140            .add_field("OptionalKey".to_string(), Field::String("My first entry".to_string())).unwrap()
1141            .build().unwrap();
1142
1143        let result = c.insert_or_update("OpenSaveCloseOpen".to_string(), entry_first.clone());
1144
1145        if let Err(e) = result {
1146            panic!("No error expected, received {}", e)
1147        } 
1148
1149        c.save().unwrap();
1150        drop(c);
1151
1152        let mut temp_dir_path = temp_dir();
1153        temp_dir_path.push("OpenSaveCloseOpen.db");
1154
1155        let mut c = Client::open(temp_dir_path).unwrap();
1156        let curent_entry = c.get("OpenSaveCloseOpen".to_string(), Field::String("This should Succeed".to_string())).unwrap();
1157        assert!(curent_entry.primary_field==entry_first.primary_field);
1158        assert!(curent_entry.fields==entry_first.fields);
1159    }
1160
1161    #[test]
1162    fn query_item() {
1163        let (mut c, table_builder) = create_client_table("QueryItems".to_string());
1164        
1165        let table = table_builder.primary_field(structs::FieldType::String).unwrap()
1166            .add_field("FirstKey".to_string(), structs::FieldType::I64).unwrap()
1167            .add_optional_field("OptionalKey".to_string(), FieldType::String).unwrap()
1168            .build().unwrap();
1169
1170        c.create_table(table).unwrap();
1171
1172        let entry_first = structs::Entry::new()
1173            .set_primary_field(Field::String("This should Succeed".to_string())).unwrap()
1174            .add_field("FirstKey".to_string(), Field::I64(123123)).unwrap()
1175            .add_field("OptionalKey".to_string(), Field::String("My first entry".to_string())).unwrap()
1176            .build().unwrap();
1177
1178        let result = c.insert("QueryItems".to_string(), entry_first.clone());
1179
1180        if let Err(e) = result {
1181            panic!("No error expected, received {}", e)
1182        } 
1183
1184        let entry_second = structs::Entry::new()
1185            .set_primary_field(Field::String("This should Succeed too".to_string())).unwrap()
1186            .add_field("FirstKey".to_string(), Field::I64(12312312)).unwrap()
1187            .add_field("OptionalKey".to_string(), Field::String("My second entry".to_string())).unwrap()
1188            .build().unwrap();
1189
1190        let result = c.insert("QueryItems".to_string(), entry_second.clone());
1191
1192        if let Err(e) = result {
1193            panic!("No error expected, received {}", e)
1194        }
1195
1196        let first_query = c.query("QueryItems".to_string(), HashMap::from_iter(vec![("OptionalKey".to_string(), Field::String("My first entry".to_string()))])).unwrap();
1197        let second_query = c.query("QueryItems".to_string(), HashMap::from_iter(vec![("FirstKey".to_string(),Field::I64(12312312))])).unwrap();
1198        
1199        assert!(first_query[0].primary_field==entry_first.primary_field);
1200        assert!(first_query[0].fields==entry_first.fields);
1201        assert!(first_query.len() == 1);
1202
1203        assert!(second_query[0].primary_field==entry_second.primary_field);
1204        assert!(second_query[0].fields==entry_second.fields);
1205        assert!(second_query.len() == 1);
1206    }
1207}