aurora_db/parser/
executor_utils.rs1use crate::error::{AqlError, ErrorCode, Result};
2use crate::parser::ast;
3
4#[derive(Debug, Clone)]
6pub enum CompiledFilter {
7 Eq(String, ast::Value),
8 Ne(String, ast::Value),
9 Gt(String, ast::Value),
10 Gte(String, ast::Value),
11 Lt(String, ast::Value),
12 Lte(String, ast::Value),
13 In(String, ast::Value),
14 NotIn(String, ast::Value),
15 Contains(String, ast::Value),
16 ContainsAny(String, ast::Value),
17 ContainsAll(String, ast::Value),
18 StartsWith(String, ast::Value),
19 EndsWith(String, ast::Value),
20 Matches(String, regex::Regex),
21 IsNull(String),
22 IsNotNull(String),
23 And(Vec<CompiledFilter>),
24 Or(Vec<CompiledFilter>),
25 Not(Box<CompiledFilter>),
26}
27
28pub fn compile_filter(filter: &ast::Filter) -> Result<CompiledFilter> {
30 match filter {
31 ast::Filter::Eq(f, v) => Ok(CompiledFilter::Eq(f.clone(), v.clone())),
32 ast::Filter::Ne(f, v) => Ok(CompiledFilter::Ne(f.clone(), v.clone())),
33 ast::Filter::Gt(f, v) => Ok(CompiledFilter::Gt(f.clone(), v.clone())),
34 ast::Filter::Gte(f, v) => Ok(CompiledFilter::Gte(f.clone(), v.clone())),
35 ast::Filter::Lt(f, v) => Ok(CompiledFilter::Lt(f.clone(), v.clone())),
36 ast::Filter::Lte(f, v) => Ok(CompiledFilter::Lte(f.clone(), v.clone())),
37 ast::Filter::In(f, v) => Ok(CompiledFilter::In(f.clone(), v.clone())),
38 ast::Filter::NotIn(f, v) => Ok(CompiledFilter::NotIn(f.clone(), v.clone())),
39 ast::Filter::Contains(f, v) => Ok(CompiledFilter::Contains(f.clone(), v.clone())),
40 ast::Filter::ContainsAny(f, v) => Ok(CompiledFilter::ContainsAny(f.clone(), v.clone())),
41 ast::Filter::ContainsAll(f, v) => Ok(CompiledFilter::ContainsAll(f.clone(), v.clone())),
42 ast::Filter::StartsWith(f, v) => Ok(CompiledFilter::StartsWith(f.clone(), v.clone())),
43 ast::Filter::EndsWith(f, v) => Ok(CompiledFilter::EndsWith(f.clone(), v.clone())),
44 ast::Filter::Matches(f, v) => {
45 if let ast::Value::String(pattern) = v {
46 let re = regex::RegexBuilder::new(pattern)
48 .size_limit(10_000_000) .dfa_size_limit(2_000_000) .build()
51 .map_err(|e| {
52 AqlError::new(
53 ErrorCode::SecurityError,
54 format!(
55 "Regex pattern '{}' is too complex or invalid: {}",
56 pattern, e
57 ),
58 )
59 })?;
60 Ok(CompiledFilter::Matches(f.clone(), re))
61 } else {
62 Err(AqlError::new(
63 ErrorCode::InvalidInput,
64 "Matches filter requires a string pattern",
65 ))
66 }
67 }
68 ast::Filter::IsNull(f) => Ok(CompiledFilter::IsNull(f.clone())),
69 ast::Filter::IsNotNull(f) => Ok(CompiledFilter::IsNotNull(f.clone())),
70 ast::Filter::And(filters) => {
71 let compiled = filters
72 .iter()
73 .map(compile_filter)
74 .collect::<Result<Vec<_>>>()?;
75 Ok(CompiledFilter::And(compiled))
76 }
77 ast::Filter::Or(filters) => {
78 let compiled = filters
79 .iter()
80 .map(compile_filter)
81 .collect::<Result<Vec<_>>>()?;
82 Ok(CompiledFilter::Or(compiled))
83 }
84 ast::Filter::Not(filter) => {
85 let compiled = compile_filter(filter)?;
86 Ok(CompiledFilter::Not(Box::new(compiled)))
87 }
88 }
89}