Skip to main content

triblespace_core/
debug.rs

1/// Diagnostic wrappers for the query engine used in tests.
2pub mod query {
3    use crate::query::Binding;
4    use crate::query::Constraint;
5    use crate::query::VariableId;
6    use crate::query::VariableSet;
7    use crate::value::RawValue;
8    use std::cell::RefCell;
9    use std::rc::Rc;
10
11    /// Constraint wrapper that records which variables are proposed during query execution.
12    pub struct DebugConstraint<C> {
13        /// The underlying constraint being observed.
14        pub constraint: C,
15        /// Shared log of variable ids in the order they were proposed.
16        pub record: Rc<RefCell<Vec<VariableId>>>,
17    }
18
19    impl<C> DebugConstraint<C> {
20        /// Wraps `constraint` and appends every proposed variable id to `record`.
21        pub fn new(constraint: C, record: Rc<RefCell<Vec<VariableId>>>) -> Self {
22            DebugConstraint { constraint, record }
23        }
24    }
25
26    impl<'a, C: Constraint<'a>> Constraint<'a> for DebugConstraint<C> {
27        fn variables(&self) -> VariableSet {
28            self.constraint.variables()
29        }
30
31        fn estimate(&self, variable: VariableId, binding: &Binding) -> Option<usize> {
32            self.constraint.estimate(variable, binding)
33        }
34
35        fn propose(&self, variable: VariableId, binding: &Binding, proposals: &mut Vec<RawValue>) {
36            self.record.borrow_mut().push(variable);
37            self.constraint.propose(variable, binding, proposals);
38        }
39
40        fn confirm(&self, variable: VariableId, binding: &Binding, proposals: &mut Vec<RawValue>) {
41            self.constraint.confirm(variable, binding, proposals);
42        }
43
44        fn influence(&self, variable: VariableId) -> VariableSet {
45            self.constraint.influence(variable)
46        }
47    }
48
49    /// Constraint wrapper that overrides cardinality estimates for selected variables.
50    pub struct EstimateOverrideConstraint<C> {
51        /// The underlying constraint whose estimates may be overridden.
52        pub constraint: C,
53        /// Per-variable estimate overrides; `None` falls through to the inner constraint.
54        pub estimates: [Option<usize>; 128],
55    }
56
57    impl<C> EstimateOverrideConstraint<C> {
58        /// Creates a wrapper with no estimate overrides.
59        pub fn new(constraint: C) -> Self {
60            EstimateOverrideConstraint {
61                constraint,
62                estimates: [None; 128],
63            }
64        }
65
66        /// Creates a wrapper with the given estimate override array.
67        pub fn with_estimates(constraint: C, estimates: [Option<usize>; 128]) -> Self {
68            EstimateOverrideConstraint {
69                constraint,
70                estimates,
71            }
72        }
73
74        /// Overrides the cardinality estimate for `variable`.
75        pub fn set_estimate(&mut self, variable: VariableId, estimate: usize) {
76            self.estimates[variable] = Some(estimate);
77        }
78    }
79
80    impl<'a, C: Constraint<'a>> Constraint<'a> for EstimateOverrideConstraint<C> {
81        fn variables(&self) -> VariableSet {
82            self.constraint.variables()
83        }
84
85        fn estimate(&self, variable: VariableId, binding: &Binding) -> Option<usize> {
86            self.estimates[variable].or_else(|| self.constraint.estimate(variable, binding))
87        }
88
89        fn propose(&self, variable: VariableId, binding: &Binding, proposals: &mut Vec<RawValue>) {
90            self.constraint.propose(variable, binding, proposals);
91        }
92
93        fn confirm(&self, variable: VariableId, binding: &Binding, proposals: &mut Vec<RawValue>) {
94            self.constraint.confirm(variable, binding, proposals);
95        }
96
97        fn influence(&self, variable: VariableId) -> VariableSet {
98            self.constraint.influence(variable)
99        }
100    }
101}