1use crate::database::Database;
5use crate::database_config::DatabaseConfig;
6use crate::database_entry::DatabaseEntry;
7use noxu_sync::Mutex;
8use std::sync::Arc;
9
10pub trait SecondaryKeyCreator: Send + Sync {
18 fn create_secondary_key(
30 &self,
31 secondary_db: &Database,
32 key: &DatabaseEntry,
33 data: &DatabaseEntry,
34 result: &mut DatabaseEntry,
35 ) -> bool;
36}
37
38pub trait SecondaryMultiKeyCreator: Send + Sync {
46 fn create_secondary_keys(
54 &self,
55 secondary_db: &Database,
56 key: &DatabaseEntry,
57 data: &DatabaseEntry,
58 results: &mut Vec<DatabaseEntry>,
59 );
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
66pub enum ForeignKeyDeleteAction {
67 Abort,
71
72 Cascade,
75
76 Nullify,
79}
80
81pub trait ForeignKeyNullifier: Send + Sync {
85 fn nullify_foreign_key(
93 &self,
94 secondary_db: &Database,
95 data: &mut DatabaseEntry,
96 ) -> bool;
97}
98
99pub trait ForeignMultiKeyNullifier: Send + Sync {
103 fn nullify_foreign_key(
111 &self,
112 secondary_db: &Database,
113 key: &DatabaseEntry,
114 data: &mut DatabaseEntry,
115 secondary_key: &DatabaseEntry,
116 ) -> bool;
117}
118
119pub struct SecondaryConfig {
160 pub base: DatabaseConfig,
162
163 pub key_creator: Option<Box<dyn SecondaryKeyCreator>>,
165
166 pub multi_key_creator: Option<Box<dyn SecondaryMultiKeyCreator>>,
168
169 pub allow_populate: bool,
174
175 pub foreign_key_database_name: Option<String>,
182
183 pub foreign_key_database: Option<Arc<Mutex<Database>>>,
191
192 pub foreign_key_delete_action: ForeignKeyDeleteAction,
194
195 pub foreign_key_nullifier: Option<Box<dyn ForeignKeyNullifier>>,
197
198 pub foreign_multi_key_nullifier: Option<Box<dyn ForeignMultiKeyNullifier>>,
200
201 pub immutable_secondary_key: bool,
205
206 pub extract_from_primary_key_only: bool,
210}
211
212impl SecondaryConfig {
213 pub fn new() -> Self {
223 Self {
224 base: DatabaseConfig::new(),
225 key_creator: None,
226 multi_key_creator: None,
227 allow_populate: false,
228 foreign_key_database_name: None,
229 foreign_key_database: None,
230 foreign_key_delete_action: ForeignKeyDeleteAction::Abort,
231 foreign_key_nullifier: None,
232 foreign_multi_key_nullifier: None,
233 immutable_secondary_key: false,
234 extract_from_primary_key_only: false,
235 }
236 }
237
238 pub fn with_allow_create(mut self, allow_create: bool) -> Self {
244 self.base.allow_create = allow_create;
245 self
246 }
247
248 pub fn with_sorted_duplicates(mut self, sorted_duplicates: bool) -> Self {
253 self.base.sorted_duplicates = sorted_duplicates;
254 self
255 }
256
257 pub fn with_allow_populate(mut self, allow_populate: bool) -> Self {
261 self.allow_populate = allow_populate;
262 self
263 }
264
265 pub fn with_key_creator(
272 mut self,
273 key_creator: Box<dyn SecondaryKeyCreator>,
274 ) -> Self {
275 self.key_creator = Some(key_creator);
276 self
277 }
278
279 pub fn with_multi_key_creator(
283 mut self,
284 multi_key_creator: Box<dyn SecondaryMultiKeyCreator>,
285 ) -> Self {
286 self.multi_key_creator = Some(multi_key_creator);
287 self
288 }
289
290 pub fn with_immutable_secondary_key(mut self, immutable: bool) -> Self {
294 self.immutable_secondary_key = immutable;
295 self
296 }
297
298 pub fn with_extract_from_primary_key_only(
302 mut self,
303 extract_only: bool,
304 ) -> Self {
305 self.extract_from_primary_key_only = extract_only;
306 self
307 }
308
309 pub fn with_foreign_key_database<S: Into<String>>(
318 mut self,
319 name: S,
320 ) -> Self {
321 self.foreign_key_database_name = Some(name.into());
322 self
323 }
324
325 pub fn with_foreign_key_database_handle(
333 mut self,
334 handle: Arc<Mutex<Database>>,
335 ) -> Self {
336 if self.foreign_key_database_name.is_none() {
340 let n = handle.lock().name().to_string();
341 self.foreign_key_database_name = Some(n);
342 }
343 self.foreign_key_database = Some(handle);
344 self
345 }
346
347 pub fn with_foreign_key_delete_action(
356 mut self,
357 action: ForeignKeyDeleteAction,
358 ) -> Self {
359 self.foreign_key_delete_action = action;
360 self
361 }
362
363 pub fn with_foreign_key_nullifier(
371 mut self,
372 nullifier: Box<dyn ForeignKeyNullifier>,
373 ) -> Self {
374 self.foreign_key_nullifier = Some(nullifier);
375 self
376 }
377
378 pub fn with_foreign_multi_key_nullifier(
386 mut self,
387 nullifier: Box<dyn ForeignMultiKeyNullifier>,
388 ) -> Self {
389 self.foreign_multi_key_nullifier = Some(nullifier);
390 self
391 }
392
393 pub(crate) fn validate(
403 &self,
404 primary_read_only: bool,
405 ) -> Result<(), String> {
406 if self.key_creator.is_some() && self.multi_key_creator.is_some() {
407 return Err(
408 "key_creator and multi_key_creator may not both be non-null"
409 .to_string(),
410 );
411 }
412 if self.foreign_key_nullifier.is_some()
413 && self.foreign_multi_key_nullifier.is_some()
414 {
415 return Err(
416 "foreign_key_nullifier and foreign_multi_key_nullifier may not both be non-null"
417 .to_string(),
418 );
419 }
420 if self.foreign_key_delete_action == ForeignKeyDeleteAction::Nullify
421 && self.foreign_key_nullifier.is_none()
422 && self.foreign_multi_key_nullifier.is_none()
423 {
424 return Err(
425 "A ForeignKeyNullifier or ForeignMultiKeyNullifier must be set when \
426 ForeignKeyDeleteAction is Nullify"
427 .to_string(),
428 );
429 }
430 if self.foreign_key_nullifier.is_some()
431 && self.multi_key_creator.is_some()
432 {
433 return Err(
434 "ForeignKeyNullifier may not be used with SecondaryMultiKeyCreator; \
435 use ForeignMultiKeyNullifier instead"
436 .to_string(),
437 );
438 }
439 if !primary_read_only
440 && self.key_creator.is_none()
441 && self.multi_key_creator.is_none()
442 {
443 return Err(
444 "key_creator or multi_key_creator must be set when the primary database \
445 is not read-only"
446 .to_string(),
447 );
448 }
449 Ok(())
450 }
451
452 #[allow(dead_code)] pub(crate) fn update_may_change_secondary(&self) -> bool {
457 !self.immutable_secondary_key && !self.extract_from_primary_key_only
458 }
459
460 #[allow(dead_code)] pub(crate) fn has_foreign_key_config(&self) -> bool {
468 self.foreign_key_database_name.is_some()
469 || self.foreign_key_database.is_some()
470 || self.foreign_key_delete_action != ForeignKeyDeleteAction::Abort
471 || self.foreign_key_nullifier.is_some()
472 || self.foreign_multi_key_nullifier.is_some()
473 }
474}
475
476impl Default for SecondaryConfig {
477 fn default() -> Self {
478 Self::new()
479 }
480}
481
482#[cfg(test)]
483mod tests {
484 use super::*;
485
486 struct SimpleKeyCreator;
487 impl SecondaryKeyCreator for SimpleKeyCreator {
488 fn create_secondary_key(
489 &self,
490 _db: &Database,
491 _key: &DatabaseEntry,
492 data: &DatabaseEntry,
493 result: &mut DatabaseEntry,
494 ) -> bool {
495 if let Some(d) = data.data_opt() {
496 result.set_data(d);
497 true
498 } else {
499 false
500 }
501 }
502 }
503
504 #[test]
505 fn test_default_config() {
506 let config = SecondaryConfig::new();
507 assert!(!config.base.allow_create);
508 assert!(!config.allow_populate);
509 assert!(!config.immutable_secondary_key);
510 assert!(!config.extract_from_primary_key_only);
511 assert_eq!(
512 config.foreign_key_delete_action,
513 ForeignKeyDeleteAction::Abort
514 );
515 assert!(config.key_creator.is_none());
516 assert!(config.multi_key_creator.is_none());
517 assert!(config.foreign_key_nullifier.is_none());
518 assert!(config.foreign_multi_key_nullifier.is_none());
519 }
520
521 #[test]
522 fn test_builder_chain() {
523 let config = SecondaryConfig::new()
524 .with_allow_create(true)
525 .with_allow_populate(true)
526 .with_sorted_duplicates(true)
527 .with_immutable_secondary_key(true)
528 .with_extract_from_primary_key_only(true)
529 .with_key_creator(Box::new(SimpleKeyCreator));
530
531 assert!(config.base.allow_create);
532 assert!(config.base.sorted_duplicates);
533 assert!(config.allow_populate);
534 assert!(config.immutable_secondary_key);
535 assert!(config.extract_from_primary_key_only);
536 assert!(config.key_creator.is_some());
537 }
538
539 #[test]
540 fn test_validate_ok() {
541 let config =
542 SecondaryConfig::new().with_key_creator(Box::new(SimpleKeyCreator));
543 assert!(config.validate(false).is_ok());
544 }
545
546 #[test]
547 fn test_validate_both_creators_fails() {
548 use crate::environment::Environment;
549 use crate::environment_config::EnvironmentConfig;
550 use tempfile::TempDir;
551 let temp_dir = TempDir::new().unwrap();
552 let env = Environment::open(
553 EnvironmentConfig::new(temp_dir.path().to_path_buf())
554 .with_allow_create(true),
555 )
556 .unwrap();
557 let db_cfg = crate::database_config::DatabaseConfig::new()
558 .with_allow_create(true);
559 let db = env.open_database(None, "vbc_db", &db_cfg).unwrap();
560
561 struct MkCreator;
562 impl SecondaryMultiKeyCreator for MkCreator {
563 fn create_secondary_keys(
564 &self,
565 _db: &Database,
566 _key: &DatabaseEntry,
567 _data: &DatabaseEntry,
568 _results: &mut Vec<DatabaseEntry>,
569 ) {
570 }
571 }
572
573 let creator = MkCreator;
575 let key = DatabaseEntry::from_bytes(b"k");
576 let data = DatabaseEntry::from_bytes(b"v");
577 let mut results: Vec<DatabaseEntry> = Vec::new();
578 creator.create_secondary_keys(&db, &key, &data, &mut results);
579
580 let config = SecondaryConfig {
581 key_creator: Some(Box::new(SimpleKeyCreator)),
582 multi_key_creator: Some(Box::new(MkCreator)),
583 ..SecondaryConfig::new()
584 };
585 assert!(config.validate(false).is_err());
586 }
587
588 #[test]
589 fn test_validate_no_creator_read_only_ok() {
590 let config = SecondaryConfig::new();
591 assert!(config.validate(true).is_ok());
593 }
594
595 #[test]
596 fn test_validate_no_creator_writable_fails() {
597 let config = SecondaryConfig::new();
598 assert!(config.validate(false).is_err());
599 }
600
601 #[test]
602 fn test_update_may_change_secondary() {
603 let config = SecondaryConfig::new();
604 assert!(config.update_may_change_secondary());
605
606 let config_imm =
607 SecondaryConfig::new().with_immutable_secondary_key(true);
608 assert!(!config_imm.update_may_change_secondary());
609
610 let config_key_only =
611 SecondaryConfig::new().with_extract_from_primary_key_only(true);
612 assert!(!config_key_only.update_may_change_secondary());
613 }
614
615 #[test]
616 fn test_foreign_key_delete_action() {
617 let config = SecondaryConfig::new()
618 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Cascade);
619 assert_eq!(
620 config.foreign_key_delete_action,
621 ForeignKeyDeleteAction::Cascade
622 );
623 }
624
625 #[test]
626 fn test_foreign_key_delete_action_nullify() {
627 let config = SecondaryConfig::new()
628 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Nullify);
629 assert_eq!(
630 config.foreign_key_delete_action,
631 ForeignKeyDeleteAction::Nullify
632 );
633 }
634
635 #[test]
636 fn test_foreign_key_delete_action_abort() {
637 let config = SecondaryConfig::new()
639 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Abort);
640 assert_eq!(
641 config.foreign_key_delete_action,
642 ForeignKeyDeleteAction::Abort
643 );
644 }
645
646 #[test]
647 fn test_with_foreign_key_nullifier() {
648 struct SimpleNullifier;
649 impl ForeignKeyNullifier for SimpleNullifier {
650 fn nullify_foreign_key(
651 &self,
652 _db: &Database,
653 _data: &mut DatabaseEntry,
654 ) -> bool {
655 false
656 }
657 }
658 let config = SecondaryConfig::new()
659 .with_foreign_key_nullifier(Box::new(SimpleNullifier));
660 assert!(config.foreign_key_nullifier.is_some());
661 }
662
663 #[test]
664 fn test_with_foreign_multi_key_nullifier() {
665 struct MultiNullifier;
666 impl ForeignMultiKeyNullifier for MultiNullifier {
667 fn nullify_foreign_key(
668 &self,
669 _db: &Database,
670 _key: &DatabaseEntry,
671 _data: &mut DatabaseEntry,
672 _secondary_key: &DatabaseEntry,
673 ) -> bool {
674 false
675 }
676 }
677 let config = SecondaryConfig::new()
678 .with_foreign_multi_key_nullifier(Box::new(MultiNullifier));
679 assert!(config.foreign_multi_key_nullifier.is_some());
680 }
681
682 #[test]
683 fn test_with_multi_key_creator() {
684 struct MkCreator;
685 impl SecondaryMultiKeyCreator for MkCreator {
686 fn create_secondary_keys(
687 &self,
688 _db: &Database,
689 _key: &DatabaseEntry,
690 _data: &DatabaseEntry,
691 _results: &mut Vec<DatabaseEntry>,
692 ) {
693 }
694 }
695 let config =
696 SecondaryConfig::new().with_multi_key_creator(Box::new(MkCreator));
697 assert!(config.multi_key_creator.is_some());
698 assert!(config.key_creator.is_none());
699 }
700
701 #[test]
702 fn test_validate_both_nullifiers_fails() {
703 use crate::environment::Environment;
704 use crate::environment_config::EnvironmentConfig;
705 use tempfile::TempDir;
706 let temp_dir = TempDir::new().unwrap();
707 let env = Environment::open(
708 EnvironmentConfig::new(temp_dir.path().to_path_buf())
709 .with_allow_create(true),
710 )
711 .unwrap();
712 let db_cfg = crate::database_config::DatabaseConfig::new()
713 .with_allow_create(true);
714 let db = env.open_database(None, "bnf_db", &db_cfg).unwrap();
715
716 struct SimpleNullifier;
717 impl ForeignKeyNullifier for SimpleNullifier {
718 fn nullify_foreign_key(
719 &self,
720 _db: &Database,
721 _data: &mut DatabaseEntry,
722 ) -> bool {
723 false
724 }
725 }
726 struct MultiNullifier;
727 impl ForeignMultiKeyNullifier for MultiNullifier {
728 fn nullify_foreign_key(
729 &self,
730 _db: &Database,
731 _key: &DatabaseEntry,
732 _data: &mut DatabaseEntry,
733 _secondary_key: &DatabaseEntry,
734 ) -> bool {
735 false
736 }
737 }
738
739 let sn = SimpleNullifier;
741 let mut data = DatabaseEntry::from_bytes(b"v");
742 assert!(!sn.nullify_foreign_key(&db, &mut data));
743 let mn = MultiNullifier;
744 let key = DatabaseEntry::from_bytes(b"k");
745 let sec = DatabaseEntry::from_bytes(b"s");
746 assert!(!mn.nullify_foreign_key(&db, &key, &mut data, &sec));
747
748 let config = SecondaryConfig {
749 key_creator: Some(Box::new(SimpleKeyCreator)),
750 foreign_key_nullifier: Some(Box::new(SimpleNullifier)),
751 foreign_multi_key_nullifier: Some(Box::new(MultiNullifier)),
752 ..SecondaryConfig::new()
753 };
754 assert!(config.validate(false).is_err());
755 let err = config.validate(false).unwrap_err();
756 assert!(
757 err.contains("foreign_key_nullifier")
758 && err.contains("foreign_multi_key_nullifier")
759 );
760 }
761
762 #[test]
763 fn test_validate_nullify_action_without_nullifier_fails() {
764 let config = SecondaryConfig::new()
765 .with_key_creator(Box::new(SimpleKeyCreator))
766 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Nullify);
767 assert!(config.validate(false).is_err());
768 let err = config.validate(false).unwrap_err();
769 assert!(err.contains("Nullify"));
770 }
771
772 #[test]
773 fn test_validate_nullify_action_with_nullifier_ok() {
774 use crate::environment::Environment;
775 use crate::environment_config::EnvironmentConfig;
776 use tempfile::TempDir;
777 let temp_dir = TempDir::new().unwrap();
778 let env = Environment::open(
779 EnvironmentConfig::new(temp_dir.path().to_path_buf())
780 .with_allow_create(true),
781 )
782 .unwrap();
783 let db_cfg = crate::database_config::DatabaseConfig::new()
784 .with_allow_create(true);
785 let db = env.open_database(None, "vnano_db", &db_cfg).unwrap();
786
787 struct SimpleNullifier;
788 impl ForeignKeyNullifier for SimpleNullifier {
789 fn nullify_foreign_key(
790 &self,
791 _db: &Database,
792 _data: &mut DatabaseEntry,
793 ) -> bool {
794 false
795 }
796 }
797
798 let sn = SimpleNullifier;
800 let mut data = DatabaseEntry::from_bytes(b"v");
801 assert!(!sn.nullify_foreign_key(&db, &mut data));
802
803 let config = SecondaryConfig::new()
804 .with_key_creator(Box::new(SimpleKeyCreator))
805 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Nullify)
806 .with_foreign_key_nullifier(Box::new(SimpleNullifier));
807 assert!(config.validate(false).is_ok());
808 }
809
810 #[test]
811 fn test_validate_nullify_action_with_multi_nullifier_ok() {
812 use crate::environment::Environment;
813 use crate::environment_config::EnvironmentConfig;
814 use tempfile::TempDir;
815 let temp_dir = TempDir::new().unwrap();
816 let env = Environment::open(
817 EnvironmentConfig::new(temp_dir.path().to_path_buf())
818 .with_allow_create(true),
819 )
820 .unwrap();
821 let db_cfg = crate::database_config::DatabaseConfig::new()
822 .with_allow_create(true);
823 let db = env.open_database(None, "vnamo_db", &db_cfg).unwrap();
824
825 struct MultiNullifier;
826 impl ForeignMultiKeyNullifier for MultiNullifier {
827 fn nullify_foreign_key(
828 &self,
829 _db: &Database,
830 _key: &DatabaseEntry,
831 _data: &mut DatabaseEntry,
832 _secondary_key: &DatabaseEntry,
833 ) -> bool {
834 false
835 }
836 }
837
838 let mn = MultiNullifier;
840 let key = DatabaseEntry::from_bytes(b"k");
841 let mut data = DatabaseEntry::from_bytes(b"v");
842 let sec = DatabaseEntry::from_bytes(b"s");
843 assert!(!mn.nullify_foreign_key(&db, &key, &mut data, &sec));
844
845 let config = SecondaryConfig::new()
846 .with_key_creator(Box::new(SimpleKeyCreator))
847 .with_foreign_key_delete_action(ForeignKeyDeleteAction::Nullify)
848 .with_foreign_multi_key_nullifier(Box::new(MultiNullifier));
849 assert!(config.validate(false).is_ok());
850 }
851
852 #[test]
853 fn test_validate_foreign_nullifier_with_multi_key_creator_fails() {
854 use crate::environment::Environment;
855 use crate::environment_config::EnvironmentConfig;
856 use tempfile::TempDir;
857 let temp_dir = TempDir::new().unwrap();
858 let env = Environment::open(
859 EnvironmentConfig::new(temp_dir.path().to_path_buf())
860 .with_allow_create(true),
861 )
862 .unwrap();
863 let db_cfg = crate::database_config::DatabaseConfig::new()
864 .with_allow_create(true);
865 let db = env.open_database(None, "vfnmkc_db", &db_cfg).unwrap();
866
867 struct MkCreator;
868 impl SecondaryMultiKeyCreator for MkCreator {
869 fn create_secondary_keys(
870 &self,
871 _db: &Database,
872 _key: &DatabaseEntry,
873 _data: &DatabaseEntry,
874 _results: &mut Vec<DatabaseEntry>,
875 ) {
876 }
877 }
878 struct SimpleNullifier;
879 impl ForeignKeyNullifier for SimpleNullifier {
880 fn nullify_foreign_key(
881 &self,
882 _db: &Database,
883 _data: &mut DatabaseEntry,
884 ) -> bool {
885 false
886 }
887 }
888
889 let creator = MkCreator;
891 let key = DatabaseEntry::from_bytes(b"k");
892 let data = DatabaseEntry::from_bytes(b"v");
893 let mut results: Vec<DatabaseEntry> = Vec::new();
894 creator.create_secondary_keys(&db, &key, &data, &mut results);
895
896 let sn = SimpleNullifier;
897 let mut d = DatabaseEntry::from_bytes(b"v");
898 assert!(!sn.nullify_foreign_key(&db, &mut d));
899
900 let config = SecondaryConfig {
901 multi_key_creator: Some(Box::new(MkCreator)),
902 foreign_key_nullifier: Some(Box::new(SimpleNullifier)),
903 ..SecondaryConfig::new()
904 };
905 let err = config.validate(false).unwrap_err();
907 assert!(
908 err.contains("ForeignKeyNullifier")
909 || err.contains("ForeignMultiKeyNullifier")
910 || err.contains("multi")
911 );
912 }
913
914 #[test]
915 fn test_default_trait() {
916 let cfg: SecondaryConfig = Default::default();
917 assert!(!cfg.allow_populate);
918 assert!(!cfg.immutable_secondary_key);
919 }
920
921 #[test]
922 fn test_update_may_change_secondary_both_false() {
923 let config = SecondaryConfig::new()
924 .with_immutable_secondary_key(false)
925 .with_extract_from_primary_key_only(false);
926 assert!(config.update_may_change_secondary());
928 }
929
930 #[test]
931 fn test_validate_multi_key_creator_read_only_ok() {
932 struct MkCreator;
933 impl SecondaryMultiKeyCreator for MkCreator {
934 fn create_secondary_keys(
935 &self,
936 _db: &Database,
937 _key: &DatabaseEntry,
938 _data: &DatabaseEntry,
939 _results: &mut Vec<DatabaseEntry>,
940 ) {
941 }
942 }
943 let config =
945 SecondaryConfig::new().with_multi_key_creator(Box::new(MkCreator));
946 assert!(config.validate(true).is_ok());
947 }
948
949 #[test]
950 fn test_validate_multi_key_creator_writable_ok() {
951 struct MkCreator;
952 impl SecondaryMultiKeyCreator for MkCreator {
953 fn create_secondary_keys(
954 &self,
955 _db: &Database,
956 _key: &DatabaseEntry,
957 _data: &DatabaseEntry,
958 _results: &mut Vec<DatabaseEntry>,
959 ) {
960 }
961 }
962 let config =
963 SecondaryConfig::new().with_multi_key_creator(Box::new(MkCreator));
964 assert!(config.validate(false).is_ok());
965 }
966
967 #[test]
975 fn test_simple_key_creator_both_branches() {
976 use crate::environment::Environment;
977 use crate::environment_config::EnvironmentConfig;
978 use tempfile::TempDir;
979
980 let temp_dir = TempDir::new().unwrap();
981 let env_config = EnvironmentConfig::new(temp_dir.path().to_path_buf())
982 .with_allow_create(true);
983 let env = Environment::open(env_config).unwrap();
984 let db_config = crate::database_config::DatabaseConfig::new()
985 .with_allow_create(true);
986 let db = env.open_database(None, "ck_test", &db_config).unwrap();
987
988 let creator = SimpleKeyCreator;
989
990 let key = DatabaseEntry::from_bytes(b"k");
992 let data_with = DatabaseEntry::from_bytes(b"some_data");
993 let mut result = DatabaseEntry::new();
994 let got =
995 creator.create_secondary_key(&db, &key, &data_with, &mut result);
996 assert!(got);
997 assert_eq!(result.data_opt().unwrap(), b"some_data");
998
999 let data_none = DatabaseEntry::new();
1001 let mut result2 = DatabaseEntry::new();
1002 let got2 =
1003 creator.create_secondary_key(&db, &key, &data_none, &mut result2);
1004 assert!(!got2);
1005 }
1006
1007 #[test]
1010 fn test_foreign_key_nullifier_impl_covered() {
1011 struct SimpleNullifier;
1012 impl ForeignKeyNullifier for SimpleNullifier {
1013 fn nullify_foreign_key(
1014 &self,
1015 _db: &Database,
1016 _data: &mut DatabaseEntry,
1017 ) -> bool {
1018 false
1019 }
1020 }
1021
1022 use crate::environment::Environment;
1023 use crate::environment_config::EnvironmentConfig;
1024 use tempfile::TempDir;
1025
1026 let temp_dir = TempDir::new().unwrap();
1027 let env_config = EnvironmentConfig::new(temp_dir.path().to_path_buf())
1028 .with_allow_create(true);
1029 let env = Environment::open(env_config).unwrap();
1030 let db_config = crate::database_config::DatabaseConfig::new()
1031 .with_allow_create(true);
1032 let db = env.open_database(None, "nul_test", &db_config).unwrap();
1033
1034 let n = SimpleNullifier;
1035 let mut data = DatabaseEntry::from_bytes(b"val");
1036 let result = n.nullify_foreign_key(&db, &mut data);
1037 assert!(!result);
1038 }
1039
1040 #[test]
1042 fn test_foreign_multi_key_nullifier_impl_covered() {
1043 struct MultiNullifier;
1044 impl ForeignMultiKeyNullifier for MultiNullifier {
1045 fn nullify_foreign_key(
1046 &self,
1047 _db: &Database,
1048 _key: &DatabaseEntry,
1049 _data: &mut DatabaseEntry,
1050 _secondary_key: &DatabaseEntry,
1051 ) -> bool {
1052 false
1053 }
1054 }
1055
1056 use crate::environment::Environment;
1057 use crate::environment_config::EnvironmentConfig;
1058 use tempfile::TempDir;
1059
1060 let temp_dir = TempDir::new().unwrap();
1061 let env_config = EnvironmentConfig::new(temp_dir.path().to_path_buf())
1062 .with_allow_create(true);
1063 let env = Environment::open(env_config).unwrap();
1064 let db_config = crate::database_config::DatabaseConfig::new()
1065 .with_allow_create(true);
1066 let db = env.open_database(None, "mknul_test", &db_config).unwrap();
1067
1068 let n = MultiNullifier;
1069 let key = DatabaseEntry::from_bytes(b"k");
1070 let mut data = DatabaseEntry::from_bytes(b"v");
1071 let sec = DatabaseEntry::from_bytes(b"s");
1072 let result = n.nullify_foreign_key(&db, &key, &mut data, &sec);
1073 assert!(!result);
1074 }
1075
1076 #[test]
1078 fn test_multi_key_creator_impl_covered() {
1079 struct MkCreator;
1080 impl SecondaryMultiKeyCreator for MkCreator {
1081 fn create_secondary_keys(
1082 &self,
1083 _db: &Database,
1084 _key: &DatabaseEntry,
1085 _data: &DatabaseEntry,
1086 results: &mut Vec<DatabaseEntry>,
1087 ) {
1088 results.push(DatabaseEntry::from_bytes(b"sec"));
1089 }
1090 }
1091
1092 use crate::environment::Environment;
1093 use crate::environment_config::EnvironmentConfig;
1094 use tempfile::TempDir;
1095
1096 let temp_dir = TempDir::new().unwrap();
1097 let env_config = EnvironmentConfig::new(temp_dir.path().to_path_buf())
1098 .with_allow_create(true);
1099 let env = Environment::open(env_config).unwrap();
1100 let db_config = crate::database_config::DatabaseConfig::new()
1101 .with_allow_create(true);
1102 let db = env.open_database(None, "mkcreator_test", &db_config).unwrap();
1103
1104 let creator = MkCreator;
1105 let key = DatabaseEntry::from_bytes(b"k");
1106 let data = DatabaseEntry::from_bytes(b"v");
1107 let mut results = Vec::new();
1108 creator.create_secondary_keys(&db, &key, &data, &mut results);
1109 assert_eq!(results.len(), 1);
1110 }
1111
1112 #[test]
1114 fn test_with_foreign_key_database() {
1115 let config = SecondaryConfig::new()
1116 .with_key_creator(Box::new(SimpleKeyCreator))
1117 .with_foreign_key_database("foreign_db");
1118 assert_eq!(
1119 config.foreign_key_database_name.as_deref(),
1120 Some("foreign_db")
1121 );
1122 assert!(config.has_foreign_key_config());
1126 }
1127
1128 #[test]
1134 fn test_all_local_trait_impls_exercised() {
1135 use crate::environment::Environment;
1136 use crate::environment_config::EnvironmentConfig;
1137 use tempfile::TempDir;
1138
1139 let temp_dir = TempDir::new().unwrap();
1141 let env_config = EnvironmentConfig::new(temp_dir.path().to_path_buf())
1142 .with_allow_create(true);
1143 let env = Environment::open(env_config).unwrap();
1144 let db_config = crate::database_config::DatabaseConfig::new()
1145 .with_allow_create(true);
1146 let db = env.open_database(None, "exercise_db", &db_config).unwrap();
1147
1148 struct NopMkCreator;
1150 impl SecondaryMultiKeyCreator for NopMkCreator {
1151 fn create_secondary_keys(
1152 &self,
1153 _db: &Database,
1154 _key: &DatabaseEntry,
1155 _data: &DatabaseEntry,
1156 _results: &mut Vec<DatabaseEntry>,
1157 ) {
1158 }
1160 }
1161
1162 let creator = NopMkCreator;
1163 let k = DatabaseEntry::from_bytes(b"k");
1164 let d = DatabaseEntry::from_bytes(b"v");
1165 let mut out: Vec<DatabaseEntry> = Vec::new();
1166 creator.create_secondary_keys(&db, &k, &d, &mut out);
1167 assert!(out.is_empty());
1168
1169 struct Nul;
1171 impl ForeignKeyNullifier for Nul {
1172 fn nullify_foreign_key(
1173 &self,
1174 _db: &Database,
1175 _data: &mut DatabaseEntry,
1176 ) -> bool {
1177 false
1178 }
1179 }
1180
1181 let n = Nul;
1182 let mut data = DatabaseEntry::from_bytes(b"v");
1183 assert!(!n.nullify_foreign_key(&db, &mut data));
1184
1185 struct MultiNul;
1187 impl ForeignMultiKeyNullifier for MultiNul {
1188 fn nullify_foreign_key(
1189 &self,
1190 _db: &Database,
1191 _key: &DatabaseEntry,
1192 _data: &mut DatabaseEntry,
1193 _secondary_key: &DatabaseEntry,
1194 ) -> bool {
1195 false
1196 }
1197 }
1198
1199 let mn = MultiNul;
1200 let key = DatabaseEntry::from_bytes(b"k");
1201 let mut data2 = DatabaseEntry::from_bytes(b"v");
1202 let sec = DatabaseEntry::from_bytes(b"s");
1203 assert!(!mn.nullify_foreign_key(&db, &key, &mut data2, &sec));
1204
1205 struct NopMkCreator2;
1207 impl SecondaryMultiKeyCreator for NopMkCreator2 {
1208 fn create_secondary_keys(
1209 &self,
1210 _db: &Database,
1211 _key: &DatabaseEntry,
1212 _data: &DatabaseEntry,
1213 _results: &mut Vec<DatabaseEntry>,
1214 ) {
1215 }
1216 }
1217
1218 let creator2 = NopMkCreator2;
1219 let mut out2: Vec<DatabaseEntry> = Vec::new();
1220 creator2.create_secondary_keys(&db, &k, &d, &mut out2);
1221
1222 struct Nul2;
1224 impl ForeignKeyNullifier for Nul2 {
1225 fn nullify_foreign_key(
1226 &self,
1227 _db: &Database,
1228 _data: &mut DatabaseEntry,
1229 ) -> bool {
1230 false
1231 }
1232 }
1233
1234 let n2 = Nul2;
1235 let mut data3 = DatabaseEntry::from_bytes(b"v");
1236 assert!(!n2.nullify_foreign_key(&db, &mut data3));
1237 }
1238}