1extern crate chrono;
2extern crate serde;
3#[macro_use]
4extern crate serde_derive;
5extern crate serde_json;
6
7use chrono::{Local, NaiveDateTime};
9use std::collections::{HashMap, HashSet};
10use std::error::Error;
11use std::fmt;
12use std::fs::File;
13use std::io::Read;
14use std::io::Write;
15use std::path::Path;
16
17#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug)]
56pub enum Data {
57 DbString(String),
58 DbI32(i32),
59 DbDateTime(NaiveDateTime),
60}
61
62impl fmt::Display for Data {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 let printable = match self {
65 Data::DbDateTime(date_time) => date_time.format("%Y-%m-%d %H:%M").to_string(),
66 Data::DbI32(number) => format!("{}", number),
67 Data::DbString(string) => string.clone(),
68 };
69 write!(f, "{}", printable)
70 }
71}
72
73impl Data {
74 fn starts_with(&self, data: &Data) -> bool {
76 if let (Data::DbString(left), Data::DbString(right)) = (self, data) {
77 left.starts_with(right)
78 } else {
79 false
80 }
81 }
82
83 fn contains(&self, data: &Data) -> bool {
85 if let (Data::DbString(left), Data::DbString(right)) = (self, data) {
86 left.contains(right)
87 } else {
88 false
89 }
90 }
91
92 pub fn now() -> Data {
94 Data::DbDateTime(Local::now().naive_local())
95 }
96
97 pub fn date(&self) -> Option<String> {
98 if let Data::DbDateTime(d) = self {
99 Some(d.format("%Y-%m-%d").to_string())
100 } else {
101 None
102 }
103 }
104}
105
106#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug, Copy, PartialOrd, Ord)]
109pub struct RowId(pub usize);
110
111#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Clone, Debug)]
113pub struct Entry {
114 pub name: String,
115 pub value: Data,
116}
117
118impl Entry {
119 pub fn new_string(name: &str, value: &str) -> Entry {
121 Entry {
122 name: String::from(name),
123 value: Db::db_string(value),
124 }
125 }
126
127 pub fn new_i32(name: &str, value: i32) -> Entry {
129 Entry {
130 name: String::from(name),
131 value: Db::db_i32(value),
132 }
133 }
134
135 pub fn compare(&self, predicate: &Predicate) -> bool {
146 match &predicate.predicate_type {
147 PredicateType::Any => predicate.entry.name == self.name,
148 PredicateType::Equal => {
149 predicate.entry.name == self.name && predicate.entry.value == self.value
150 }
151 PredicateType::StartsWith => {
152 self.name == predicate.entry.name && self.value.starts_with(&predicate.entry.value)
153 }
154 PredicateType::Contains => {
155 self.name == predicate.entry.name && self.value.contains(&predicate.entry.value)
156 }
157 }
158 }
159
160 pub fn compare_all(entries: &[Entry], predicate: &Predicate) -> bool {
161 for entry in entries {
162 if entry.compare(predicate) {
163 return true;
164 }
165 }
166 false
167 }
168
169 pub fn check_by_name(entries: &[Entry], name: &str) -> bool {
171 for entry in entries {
172 if entry.name == name {
173 return true;
174 }
175 }
176 false
177 }
178
179 pub fn check_by_value(entries: &[Entry], name: &str, value: &Data) -> bool {
181 for entry in entries {
182 if entry.name == name && &entry.value == value {
183 return true;
184 }
185 }
186 false
187 }
188
189 pub fn get_first_by_name(entries: &[Entry], name: &str) -> Option<Entry> {
191 for entry in entries {
192 if entry.name == name {
193 return Some(entry.clone());
194 }
195 }
196 None
197 }
198
199 pub fn get_first_by_name_mut<'a>(
201 entries: &'a mut Vec<Entry>,
202 name: &str,
203 ) -> Option<&'a mut Entry> {
204 for entry in entries {
205 if entry.name == name {
206 return Some(entry);
207 }
208 }
209 None
210 }
211}
212
213#[derive(PartialEq, Debug)]
214pub enum PredicateType {
215 Equal,
216 StartsWith,
217 Contains,
218 Any,
219}
220
221#[derive(Debug)]
235pub struct Predicate {
236 pub predicate_type: PredicateType,
237 pub entry: Entry,
238}
239
240impl Predicate {
241 pub fn new_equal_i32(name: &str, value: i32) -> Predicate {
243 Predicate {
244 predicate_type: PredicateType::Equal,
245 entry: Entry {
246 name: String::from(name),
247 value: Db::db_i32(value),
248 },
249 }
250 }
251
252 pub fn new_any_string(name: &str) -> Predicate {
255 Predicate {
256 predicate_type: PredicateType::Any,
257 entry: Entry {
258 name: String::from(name),
259 value: Db::db_string(""),
260 },
261 }
262 }
263
264 pub fn new_equal_string(name: &str, value: &str) -> Predicate {
267 Predicate {
268 predicate_type: PredicateType::Equal,
269 entry: Entry {
270 name: String::from(name),
271 value: Db::db_string(value),
272 },
273 }
274 }
275
276 pub fn new_starts_with(name: &str, value: &str) -> Predicate {
279 Predicate {
280 predicate_type: PredicateType::StartsWith,
281 entry: Entry {
282 name: String::from(name),
283 value: Db::db_string(value),
284 },
285 }
286 }
287 pub fn new_contains(name: &str, value: &str) -> Predicate {
290 Predicate {
291 predicate_type: PredicateType::Contains,
292 entry: Entry {
293 name: String::from(name),
294 value: Db::db_string(value),
295 },
296 }
297 }
298}
299
300#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
301struct Row {
302 pub row_id: RowId,
303 pub entry: Entry,
304}
305
306#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
316pub struct Db {
317 full_filename: String,
318 row_max: RowId,
319 by_row_id: HashMap<RowId, Vec<Entry>>,
320 by_name: HashMap<String, HashSet<RowId>>,
321 by_value: HashMap<Entry, HashSet<RowId>>,
322}
323
324impl Db {
325 pub fn new(filename: &str) -> Db {
327 Db {
328 full_filename: Db::build_filename(filename),
329 row_max: RowId(0),
330 by_row_id: HashMap::new(),
331 by_name: HashMap::new(),
332 by_value: HashMap::new(),
333 }
334 }
335
336 pub fn load(filename: &str) -> Result<Db, Box<Error>> {
342 let full_filename = Db::build_filename(filename);
343 let mut file = File::open(full_filename)?;
344 let mut contents = String::new();
345 file.read_to_string(&mut contents)?;
346 let mut db = Db::new(filename);
347 let row_id_map: HashMap<RowId, Vec<Entry>> = serde_json::from_str(&contents)?;
348 for (_row_id, entries) in row_id_map {
349 db.add_row(entries);
350 }
351 Ok(db)
352 }
353
354 pub fn save(&mut self) -> Result<(), Box<Error>> {
357 self.by_row_id.retain(|_key, value| !value.is_empty());
358 let path = Path::new(&self.full_filename);
359 let mut file = File::create(&path)?;
360 let serialized = match serde_json::to_string_pretty(&self.by_row_id) {
361 Ok(s) => s,
362 Err(ref e) => {
363 println!("{}|{}", e.description(), e);
364 panic!()
365 }
366 };
367 file.write_all(serialized.as_bytes())?;
368 Ok(())
369 }
370
371 pub fn get_name(&self) -> String {
373 if self.full_filename.len() < 6 {
375 panic!("Could not Db::get_name()");
376 }
377 self.full_filename[5..].to_string()
378 }
379
380 pub fn db_string(v: &str) -> Data {
382 Data::DbString(String::from(v))
383 }
384
385 pub fn db_i32(v: i32) -> Data {
387 Data::DbI32(v)
388 }
389
390 pub fn find_first_i32(&self, name: &str) -> Option<i32> {
400 if let Some(row_id) = self.find_first_row_id_by_name(name) {
401 if let Some(entries) = self.by_row_id.get(&row_id) {
402 if let Some(entry) = Entry::get_first_by_name(entries, name) {
403 if let Data::DbI32(value) = entry.value {
404 return Some(value);
405 }
406 }
407 }
408 }
409 None
410 }
411
412 pub fn find_first_string(&self, name: &str) -> Option<String> {
422 if let Some(row_id) = self.find_first_row_id_by_name(name) {
423 if let Some(entries) = self.by_row_id.get(&row_id) {
424 if let Some(entry) = Entry::get_first_by_name(entries, name) {
425 if let Data::DbString(value) = entry.value {
426 return Some(value);
427 }
428 }
429 }
430 }
431 None
432 }
433
434 pub fn db_datetime(v: &str) -> Result<Data, Box<Error>> {
436 let fmt = "%Y-%m-%d %H:%M:%S";
437 let r = NaiveDateTime::parse_from_str(v, fmt)?;
438 Ok(Data::DbDateTime(r))
439 }
440
441 fn add_name(&mut self, name: String, row_id: RowId) {
442 let row_ids = self.by_name.entry(name).or_insert_with(HashSet::new);
443 row_ids.insert(row_id);
444 }
445
446 fn add_value(&mut self, value: Entry, row_id: RowId) {
447 let row_ids = self.by_value.entry(value).or_insert_with(HashSet::new);
448 row_ids.insert(row_id);
449 }
450
451 pub fn add_i32(&mut self, name: &str, value: i32) -> RowId {
453 self.add_row(vec![Entry::new_i32(name, value)])
454 }
455
456 pub fn add_string(&mut self, name: &str, value: &str) -> RowId {
458 self.add_row(vec![Entry::new_string(name, value)])
459 }
460
461 pub fn add_row(&mut self, entries: Vec<Entry>) -> RowId {
463 let row_id = self.next();
464 for entry in &entries {
465 self.add_name(entry.name.clone(), row_id);
466 self.add_value(entry.clone(), row_id);
467 }
468 self.by_row_id.insert(row_id, entries);
469 row_id
470 }
471
472 pub fn add_or_update_entry(&mut self, row_id: RowId, new_entry: Entry) {
475 self.remove_by_name(row_id, &new_entry.name);
476 self.add_row_id_entry(row_id, new_entry);
477 }
478
479 pub fn remove_by_name(&mut self, row_id: RowId, name: &str) {
482 if let Some(entries) = self.by_row_id.get(&row_id) {
483 for entry in entries.iter() {
484 if let Some(row_ids) = self.by_name.get_mut(&entry.name) {
485 row_ids.remove(&row_id);
486 }
487 if let Some(row_ids) = self.by_value.get_mut(&entry) {
488 row_ids.remove(&row_id);
489 }
490 }
491 }
492
493 if let Some(entries) = self.by_row_id.get_mut(&row_id) {
494 entries.retain(|entry| entry.name != name);
495 }
496
497 if let Some(entries) = self.by_row_id.get(&row_id) {
498 for entry in entries.iter() {
499 if let Some(row_ids) = self.by_name.get_mut(&entry.name) {
500 row_ids.insert(row_id);
501 }
502 if let Some(row_ids) = self.by_value.get_mut(&entry) {
503 row_ids.insert(row_id);
504 }
505 }
506 }
507 }
508
509 pub fn remove_by_row_id(&mut self, row_id: RowId) {
511 if let Some(entries) = self.by_row_id.get(&row_id) {
512 for entry in entries.iter() {
513 if let Some(row_ids) = self.by_name.get_mut(&entry.name) {
514 row_ids.remove(&row_id);
515 }
516 if let Some(row_ids) = self.by_value.get_mut(&entry) {
517 row_ids.remove(&row_id);
518 }
519 }
520 }
521
522 self.by_row_id.remove(&row_id);
523 }
524
525 pub fn add_row_id_entry(&mut self, row_id: RowId, entry: Entry) {
527 self.by_row_id
528 .entry(row_id)
529 .or_insert_with(Vec::new)
530 .push(entry.clone());
531 self.by_name
532 .entry(entry.name.clone())
533 .or_insert_with(HashSet::new)
534 .insert(row_id);
535 self.by_value
536 .entry(entry)
537 .or_insert_with(HashSet::new)
538 .insert(row_id);
539 }
540
541 pub fn delete_rows(&mut self, row_ids: &[RowId]) {
564 for row_id in row_ids {
565 self.remove_by_row_id(*row_id);
566 }
567 }
568
569 pub fn delete_entry_all(&mut self, name: &str) {
573 let row_ids = self.find_row_ids_by_name(name);
574 for row_id in row_ids {
575 self.remove_by_name(row_id, name);
576 }
577 }
578
579 pub fn find_row_ids_by_name(&self, name: &str) -> Vec<RowId> {
581 if let Some(rows) = self.by_name.get(name) {
582 rows.iter().cloned().collect::<Vec<RowId>>()
583 } else {
584 vec![]
585 }
586 }
587
588 pub fn find_row_ids_by_value(&self, name: &str, value: &Data) -> Vec<RowId> {
591 let entry = Entry {
592 name: name.to_string(),
593 value: value.clone(),
594 };
595 if let Some(rows) = self.by_value.get(&entry) {
596 rows.iter().cloned().collect::<Vec<RowId>>()
597 } else {
598 vec![]
599 }
600 }
601
602 pub fn find_first_row_id_by_name(&self, name: &str) -> Option<RowId> {
604 if let Some(rows) = self.by_name.get(name) {
605 rows.iter().cloned().next()
606 } else {
607 None
608 }
609 }
610
611 pub fn find_first_row_id_by_value(&self, name: &str, value: &Data) -> Option<RowId> {
613 let entry = Entry {
614 name: name.to_string(),
615 value: value.clone(),
616 };
617 if let Some(rows) = self.by_value.get(&entry) {
618 rows.iter().cloned().next()
619 } else {
620 None
621 }
622 }
623
624 pub fn find_first_entry_by_name(&self, row_id: RowId, name: &str) -> Option<Entry> {
626 Entry::get_first_by_name(&self.by_row_id[&row_id], name)
627 }
628
629 pub fn find_by_predicate(&self, predicate: &Predicate) -> Vec<RowId> {
630 if predicate.predicate_type == PredicateType::Equal {
631 if let Some(row_ids) = self.by_value.get(&predicate.entry) {
632 row_ids.iter().cloned().collect::<Vec<RowId>>()
633 } else {
634 vec![]
635 }
636 } else {
637 self.by_row_id
638 .iter()
639 .filter(|(_row_id, entries)| Entry::compare_all(entries, predicate))
640 .map(|(row_id, _entries)| *row_id)
641 .collect::<Vec<RowId>>()
642 }
643 }
644
645 pub fn find_row_ids_by_predicate(
677 &self,
678 predicates: &[Predicate],
679 max_results: Option<usize>,
680 ) -> Vec<RowId> {
681 let max_results = if let Some(max_results) = max_results {
682 max_results
683 } else {
684 self.by_row_id.len()
685 };
686
687 if predicates.is_empty() {
688 self.find_all_row_ids()
689 } else {
690 let predicate0 = &predicates[0];
691 let mut row_ids = self.find_by_predicate(predicate0);
692
693 for predicate in &predicates[1..] {
694 let new_row_ids = row_ids
695 .iter()
696 .filter(|&row_id| self.match_row(*row_id, predicate))
697 .cloned()
698 .collect::<Vec<RowId>>();
699 row_ids = new_row_ids;
700 }
701 if max_results < row_ids.len() {
702 let _ = row_ids.drain(max_results..).collect::<Vec<RowId>>();
703 }
704 row_ids.sort();
705 row_ids.dedup();
706 row_ids
707 }
708 }
709
710 pub fn find_all_row_ids(&self) -> Vec<RowId> {
712 self.by_row_id.keys().cloned().collect::<Vec<RowId>>()
713 }
714
715 #[cfg(test)]
716 pub fn find_entries_by_predicate(
717 &self,
718 predicates: &[Predicate],
719 entries: &[&str],
720 ) -> Vec<Vec<Entry>> {
721 let row_ids = self.find_row_ids_by_predicate(predicates, None);
722 self.entries_from_row_ids(&row_ids, entries)
723 }
724
725 pub fn entries_from_row_ids(&self, row_ids: &[RowId], names: &[&str]) -> Vec<Vec<Entry>> {
727 let names = names.iter().map(|s| s.to_string()).collect::<Vec<String>>();
728 let mut result: Vec<Vec<Entry>> = vec![];
729 for row_id in row_ids {
730 let entries = &self.by_row_id[&row_id];
731
732 let mut ordered: Vec<Entry> = vec![];
733 for name in &names {
734 for entry in entries.iter().filter(|entry| &entry.name == name) {
735 ordered.push(entry.clone());
736 }
737 }
738
739 result.push(ordered);
740 }
741 result
742 }
743
744 fn match_row(&self, row_id: RowId, predicate: &Predicate) -> bool {
746 let entries = &self.by_row_id[&row_id];
747 Entry::compare_all(&entries, predicate)
748 }
749
750 fn next(&mut self) -> RowId {
751 self.row_max.0 += 1;
752 self.row_max
753 }
754
755 fn build_filename(name: &str) -> String {
756 format!("save/{}", name)
757 }
758
759 #[cfg(test)]
760 pub fn debug_rows(&self, row_ids: &[RowId]) -> Vec<Vec<Entry>> {
761 let mut result: Vec<Vec<Entry>> = vec![];
762 for row_id in row_ids {
763 let entries = &self.by_row_id[&row_id];
764 result.push(entries.clone());
765 }
766 result
767 }
768}
769
770mod tests {
771 #[cfg(test)]
772 use super::{Data, Db, Entry, Predicate, RowId};
773 #[cfg(test)]
774 use chrono::NaiveDateTime;
775
776 #[test]
777 fn match_row() {
778 let db = new_db_with_entries("testdb");
779
780 let p1 = Predicate::new_equal_string("name", "coche");
781 let p2 = Predicate::new_starts_with("name", "co");
782 let p3 = Predicate::new_contains("name", "och");
783
784 println!("{:?}", db.debug_rows(&vec![RowId(2)]));
785 println!("{:?}", db.debug_rows(&vec![RowId(1)]));
786
787 assert_eq!(db.match_row(RowId(2), &p1), true);
788 assert_eq!(db.match_row(RowId(2), &p2), true);
789 assert_eq!(db.match_row(RowId(2), &p3), true);
790
791 assert_eq!(db.match_row(RowId(1), &p1), false);
792 assert_eq!(db.match_row(RowId(1), &p2), false);
793 assert_eq!(db.match_row(RowId(1), &p3), false);
794 }
795
796 #[test]
797 fn starts_with_contains() {
798 let s1 = Db::db_string("hello");
799 let s2 = Db::db_string("hello world");
800 let s3 = Db::db_string("o wor");
801 assert!(s2.starts_with(&s1));
802 assert_eq!(s1.starts_with(&s2), false);
803 assert!(s2.contains(&s3));
804 assert_eq!(s3.contains(&s2), false);
805 }
806
807 #[test]
808 fn compare() {
809 let p1 = Predicate::new_equal_string("set", "es-en");
810 let p2 = Predicate::new_starts_with("set", "es");
811 let p3 = Predicate::new_contains("set", "s-e");
812
813 let e1 = Entry {
814 name: String::from("set"),
815 value: Db::db_string("es-en"),
816 };
817
818 let e2 = Entry {
819 name: String::from("set"),
820 value: Db::db_string("en-es"),
821 };
822
823 assert!(e1.compare(&p1));
824 assert_eq!(e2.compare(&p1), false);
825
826 assert!(e1.compare(&p2));
827 assert_eq!(e2.compare(&p2), false);
828
829 assert!(e1.compare(&p3));
830 assert_eq!(e2.compare(&p3), false);
831 }
832
833 #[cfg(test)]
834 fn new_db_with_entries(name: &str) -> Db {
835 let mut db = Db::new(name);
836 let _id = db.add_row(vec![
837 Entry {
838 name: String::from("set"),
839 value: Db::db_string("es-en"),
840 },
841 Entry {
842 name: String::from("name"),
843 value: Db::db_string("disfrutar"),
844 },
845 Entry {
846 name: String::from("value"),
847 value: Db::db_string("to enjoy"),
848 },
849 ]);
850 let _id = db.add_row(vec![
851 Entry {
852 name: String::from("set"),
853 value: Db::db_string("es-en"),
854 },
855 Entry {
856 name: String::from("name"),
857 value: Db::db_string("coche"),
858 },
859 Entry {
860 name: String::from("value"),
861 value: Db::db_string("car"),
862 },
863 ]);
864 db
865 }
866
867 #[cfg(test)]
868 fn check_single_entries(db: &Db) {
869 assert_eq!(db.by_row_id.len(), 2);
870
871 for value in &db.by_value {
872 println!("{:?}", value);
873 }
874 let row_ids = db.find_row_ids_by_value("set", &Db::db_string("es-en"));
875 assert_eq!(row_ids.len(), 2);
876
877 let row_ids = db.find_row_ids_by_value("value", &Db::db_string("car"));
878 println!("find_row_ids_by_value(): {:?}", row_ids);
879 assert_eq!(row_ids.len(), 1);
880 }
881
882 #[test]
883 fn find_row_ids_by_predicate() {
884 let name = "testdb";
885 let db = new_db_with_entries(name);
886
887 let predicates1 = vec![Predicate::new_equal_string("set", "es-en")];
888 let predicates2 = vec![
889 Predicate::new_equal_string("set", "es-en"),
890 Predicate::new_equal_string("name", "disfrutar"),
891 ];
892
893 let row_ids = db.find_row_ids_by_predicate(&predicates1, None);
894 assert_eq!(row_ids, vec![RowId(1), RowId(2)]);
895
896 let row_ids = db.find_row_ids_by_predicate(&predicates2, None);
897 assert_eq!(row_ids, vec![RowId(1)]);
898 }
899
900 #[test]
901 fn find_entries_by_predicate() {
902 let name = "testdb";
903 let db = new_db_with_entries(name);
904
905 let predicates = vec![Predicate::new_equal_string("set", "es-en")];
906
907 let result1 = vec![
908 vec![Entry {
909 name: String::from("name"),
910 value: Db::db_string("disfrutar"),
911 }],
912 vec![Entry {
913 name: String::from("name"),
914 value: Db::db_string("coche"),
915 }],
916 ];
917
918 let result2 = vec![
919 vec![
920 Entry {
921 name: String::from("name"),
922 value: Db::db_string("disfrutar"),
923 },
924 Entry {
925 name: String::from("value"),
926 value: Db::db_string("to enjoy"),
927 },
928 ],
929 vec![
930 Entry {
931 name: String::from("name"),
932 value: Db::db_string("coche"),
933 },
934 Entry {
935 name: String::from("value"),
936 value: Db::db_string("car"),
937 },
938 ],
939 ];
940
941 let result = db.find_entries_by_predicate(&predicates, &vec!["name"]);
942 assert_eq!(result, result1);
943
944 let result = db.find_entries_by_predicate(&predicates, &vec!["name", "value"]);
945 assert_eq!(result, result2);
946 }
947
948 #[test]
949 fn load_and_save() {
950 let name = "testdb";
951 let mut db = new_db_with_entries(name);
952 db.save().unwrap();
953 let db = Db::load(name).unwrap();
954 check_single_entries(&db);
955 }
956
957 #[test]
958 fn add_row() {
959 let db = new_db_with_entries("testdb");
960 check_single_entries(&db);
961 }
962
963 #[test]
964 fn data_types() {
965 let t = "Test";
966 assert_eq!(Data::DbString(String::from(t)), Db::db_string(t));
967 let t = 42;
968 assert_eq!(Data::DbI32(t), Db::db_i32(t));
969 let fmt = "%Y-%m-%d %H:%M:%S";
970 let t = "2013-11-22 12:00:00";
971 let dt = NaiveDateTime::parse_from_str(t, fmt).unwrap();
972 assert_eq!(Data::DbDateTime(dt), Db::db_datetime(t).unwrap());
973 }
974
975 #[test]
976 fn add_or_update_entry_add() {
977 let mut db = new_db_with_entries("testdb");
978
979 println!("Before update/add: {:?}", db.debug_rows(&vec![RowId(2)]));
980 db.add_or_update_entry(
981 RowId(2),
982 Entry {
983 name: String::from("new entry"),
984 value: Db::db_string("new entry content"),
985 },
986 );
987 println!("After update/add: {:?}", db.debug_rows(&vec![RowId(2)]));
988
989 for (i, row) in db.by_row_id.iter().enumerate() {
990 println!("row: {} {:?}", i, row);
991 }
992 assert_eq!(db.find_first_row_id_by_name("new entry"), Some(RowId(2)));
993 assert_eq!(
994 db.find_first_row_id_by_value("new entry", &Db::db_string("new entry content")),
995 Some(RowId(2))
996 );
997 }
998
999 #[test]
1000 fn add_or_update_entry_update() {
1001 let mut db = new_db_with_entries("testdb");
1002
1003 println!("{:?}", db.debug_rows(&vec![RowId(2)]));
1004 db.add_or_update_entry(
1005 RowId(2),
1006 Entry {
1007 name: String::from("new entry"),
1008 value: Db::db_string("new entry content"),
1009 },
1010 );
1011 db.add_or_update_entry(
1012 RowId(2),
1013 Entry {
1014 name: String::from("new entry"),
1015 value: Db::db_string("new entry content updated"),
1016 },
1017 );
1018 println!("{:?}", db.debug_rows(&vec![RowId(2)]));
1019 for (row_id, entries) in db.by_row_id.iter() {
1020 println!("{:?}", row_id);
1021 for entry in entries {
1022 println!(" {:?}", entry);
1023 }
1024 }
1025 assert_eq!(
1026 db.find_first_row_id_by_value("new entry", &Db::db_string("new entry content updated")),
1027 Some(RowId(2))
1028 );
1029 }
1030
1031 #[test]
1032 fn delete_entry_all() {
1033 let mut db = new_db_with_entries("testdb");
1034
1035 let mut add_row = |n| {
1036 if let Some(_entry) = db.by_row_id.get(&RowId(n)) {
1037 println!("{:?}", db.debug_rows(&vec![RowId(n)]));
1038 }
1039 db.add_row_id_entry(
1040 RowId(n),
1041 Entry {
1042 name: String::from("new entry"),
1043 value: Db::db_string(&format!("new col for row {}", n)),
1044 },
1045 );
1046 };
1047 add_row(1);
1048 add_row(2);
1049 add_row(3);
1050 for (row_id, entries) in db.by_row_id.iter() {
1051 println!("{:?}", row_id);
1052 for entry in entries {
1053 println!(" {:?}", entry);
1054 }
1055 }
1056
1057 let row_ids = db.find_row_ids_by_name("new entry");
1058 assert_eq!(row_ids.len(), 3);
1059 assert!(row_ids.contains(&RowId(1)));
1060 assert!(row_ids.contains(&RowId(2)));
1061 assert!(row_ids.contains(&RowId(3)));
1062
1063 println!("Deleting entries...");
1064 db.delete_entry_all("new entry");
1065
1066 for (row_id, entries) in db.by_row_id.iter() {
1067 println!("{:?}", row_id);
1068 for entry in entries {
1069 println!(" {:?}", entry);
1070 }
1071 }
1072
1073 let row_ids = db.find_row_ids_by_name("new entry");
1074 assert_eq!(row_ids.len(), 0);
1075
1076 let row_ids = db.find_row_ids_by_name("set");
1077 assert_eq!(row_ids.len(), 2);
1078 assert!(row_ids.contains(&RowId(1)));
1079 assert!(row_ids.contains(&RowId(2)));
1080 assert!(!row_ids.contains(&RowId(3)));
1081
1082 let row_ids = db.find_row_ids_by_name("name");
1083 assert_eq!(row_ids.len(), 2);
1084 assert!(row_ids.contains(&RowId(1)));
1085 assert!(row_ids.contains(&RowId(2)));
1086 assert!(!row_ids.contains(&RowId(3)));
1087 }
1088
1089 #[test]
1090 fn find_all_row_ids() {
1091 let db = new_db_with_entries("testdb");
1092 let row_ids = db.find_all_row_ids();
1093 assert_eq!(row_ids.len(), 2);
1094 assert!(row_ids.contains(&RowId(1)));
1095 assert!(row_ids.contains(&RowId(2)));
1096 }
1097
1098 #[test]
1099 fn find_row_ids_by_value() {
1100 let db = new_db_with_entries("testdb");
1101 let entry = Entry::new_string("name", "coche");
1102 let row_id = db.by_value[&entry].iter().next().unwrap();
1103 let entry_new = db.by_row_id[row_id]
1104 .iter()
1105 .filter(|entry| &entry.name == "name")
1106 .next()
1107 .unwrap();
1108 assert_eq!(&entry, entry_new);
1109 }
1110}