sql_cli/data/
evaluation_context.rs

1use regex::Regex;
2use std::collections::HashMap;
3use std::sync::Arc;
4
5/// Context for query evaluation that can cache expensive computations
6/// like compiled regexes across multiple row evaluations
7#[derive(Debug, Clone)]
8pub struct EvaluationContext {
9    /// Cache of compiled regexes for LIKE patterns
10    /// Key is the SQL LIKE pattern, value is the compiled regex
11    regex_cache: HashMap<String, Arc<Regex>>,
12
13    /// Case insensitive mode
14    case_insensitive: bool,
15
16    /// Statistics for debugging
17    regex_compilations: usize,
18    regex_cache_hits: usize,
19}
20
21impl EvaluationContext {
22    pub fn new(case_insensitive: bool) -> Self {
23        Self {
24            regex_cache: HashMap::new(),
25            case_insensitive,
26            regex_compilations: 0,
27            regex_cache_hits: 0,
28        }
29    }
30
31    /// Get or compile a regex for a SQL LIKE pattern
32    pub fn get_or_compile_like_regex(&mut self, like_pattern: &str) -> Result<Arc<Regex>, String> {
33        // Check cache first
34        if let Some(regex) = self.regex_cache.get(like_pattern) {
35            self.regex_cache_hits += 1;
36            return Ok(Arc::clone(regex));
37        }
38
39        // Convert SQL LIKE pattern to regex pattern
40        let regex_pattern = like_pattern.replace('%', ".*").replace('_', ".");
41
42        // Compile the regex
43        let regex = regex::RegexBuilder::new(&format!("^{}$", regex_pattern))
44            .case_insensitive(self.case_insensitive)
45            .build()
46            .map_err(|e| format!("Invalid LIKE pattern '{}': {}", like_pattern, e))?;
47
48        let regex_arc = Arc::new(regex);
49        self.regex_cache
50            .insert(like_pattern.to_string(), Arc::clone(&regex_arc));
51        self.regex_compilations += 1;
52
53        Ok(regex_arc)
54    }
55
56    pub fn get_stats(&self) -> (usize, usize) {
57        (self.regex_compilations, self.regex_cache_hits)
58    }
59
60    pub fn is_case_insensitive(&self) -> bool {
61        self.case_insensitive
62    }
63}
64
65impl Default for EvaluationContext {
66    fn default() -> Self {
67        Self::new(false)
68    }
69}