uni_query/query/rewrite/
context.rs1use crate::query::rewrite::error::RewriteError;
3use std::collections::HashMap;
4
5#[derive(Default)]
10pub struct RewriteContext {
11 pub scope: HashMap<String, VariableInfo>,
13
14 pub stats: RewriteStats,
16
17 pub config: RewriteConfig,
19}
20
21impl RewriteContext {
22 pub fn new() -> Self {
24 Self::default()
25 }
26
27 pub fn with_config(config: RewriteConfig) -> Self {
29 Self {
30 scope: HashMap::new(),
31 stats: RewriteStats::default(),
32 config,
33 }
34 }
35
36 pub fn get_variable(&self, name: &str) -> Option<&VariableInfo> {
38 self.scope.get(name)
39 }
40
41 pub fn add_variable(&mut self, name: String, info: VariableInfo) {
43 self.scope.insert(name, info);
44 }
45}
46
47#[derive(Debug, Clone)]
49pub struct VariableInfo {
50 pub name: String,
52
53 pub label: Option<String>,
55
56 pub is_edge: bool,
58
59 pub properties: HashMap<String, PropertyType>,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65pub enum PropertyType {
66 String,
68
69 Integer,
71
72 Float,
74
75 Boolean,
77
78 DateTime,
80
81 List,
83
84 Map,
86
87 Unknown,
89}
90
91#[derive(Debug, Default, Clone)]
93pub struct RewriteStats {
94 pub functions_visited: usize,
96
97 pub functions_rewritten: usize,
99
100 pub functions_skipped: usize,
102
103 pub errors: Vec<RewriteError>,
105
106 pub rule_stats: HashMap<String, RuleStats>,
108}
109
110impl RewriteStats {
111 fn rule_stats_mut(&mut self, rule_name: &str) -> &mut RuleStats {
113 self.rule_stats.entry(rule_name.to_string()).or_default()
114 }
115
116 pub fn record_success(&mut self, rule_name: &str) {
118 self.functions_rewritten += 1;
119 self.rule_stats_mut(rule_name).record_success();
120 }
121
122 pub fn record_failure(&mut self, rule_name: &str, error: RewriteError) {
124 self.functions_skipped += 1;
125 self.rule_stats_mut(rule_name).record_failure(error.clone());
126 self.errors.push(error);
127 }
128
129 pub fn record_visit(&mut self) {
131 self.functions_visited += 1;
132 }
133}
134
135#[derive(Debug, Default, Clone)]
137pub struct RuleStats {
138 pub attempts: usize,
140
141 pub successes: usize,
143
144 pub failures: HashMap<String, usize>,
146}
147
148impl RuleStats {
149 fn record_success(&mut self) {
150 self.attempts += 1;
151 self.successes += 1;
152 }
153
154 fn record_failure(&mut self, error: RewriteError) {
155 self.attempts += 1;
156 let error_key = format!("{error:?}");
157 *self.failures.entry(error_key).or_default() += 1;
158 }
159}
160
161#[derive(Debug, Clone)]
163pub struct RewriteConfig {
164 pub enable_temporal: bool,
166
167 pub enable_spatial: bool,
169
170 pub enable_property: bool,
172
173 pub fallback_to_scalar: bool,
175
176 pub verbose_logging: bool,
178}
179
180impl Default for RewriteConfig {
181 fn default() -> Self {
182 Self {
183 enable_temporal: true,
184 enable_spatial: false,
185 enable_property: false,
186 fallback_to_scalar: true,
187 verbose_logging: false,
188 }
189 }
190}
191
192impl RewriteConfig {
193 pub fn all_enabled() -> Self {
195 Self {
196 enable_temporal: true,
197 enable_spatial: true,
198 enable_property: true,
199 fallback_to_scalar: true,
200 verbose_logging: false,
201 }
202 }
203
204 pub fn all_disabled() -> Self {
206 Self {
207 enable_temporal: false,
208 enable_spatial: false,
209 enable_property: false,
210 fallback_to_scalar: true,
211 verbose_logging: false,
212 }
213 }
214
215 pub fn with_verbose_logging(mut self) -> Self {
217 self.verbose_logging = true;
218 self
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn test_context_default() {
228 let ctx = RewriteContext::default();
229 assert!(ctx.scope.is_empty());
230 assert_eq!(ctx.stats.functions_visited, 0);
231 assert!(ctx.config.enable_temporal);
232 }
233
234 #[test]
235 fn test_stats_recording() {
236 let mut stats = RewriteStats::default();
237
238 stats.record_success("test.func");
239 assert_eq!(stats.functions_rewritten, 1);
240 assert_eq!(stats.rule_stats.get("test.func").unwrap().successes, 1);
241
242 stats.record_failure(
243 "test.func",
244 RewriteError::NotApplicable {
245 reason: "test".into(),
246 },
247 );
248 assert_eq!(stats.functions_skipped, 1);
249 assert_eq!(stats.errors.len(), 1);
250 }
251
252 #[test]
253 fn test_config_builders() {
254 let all_enabled = RewriteConfig::all_enabled();
255 assert!(all_enabled.enable_temporal);
256 assert!(all_enabled.enable_spatial);
257 assert!(all_enabled.enable_property);
258
259 let all_disabled = RewriteConfig::all_disabled();
260 assert!(!all_disabled.enable_temporal);
261 assert!(!all_disabled.enable_spatial);
262 assert!(!all_disabled.enable_property);
263 }
264}