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 StartsWith(String, ast::Value),
17 EndsWith(String, ast::Value),
18 Matches(String, regex::Regex),
19 IsNull(String),
20 IsNotNull(String),
21 And(Vec<CompiledFilter>),
22 Or(Vec<CompiledFilter>),
23 Not(Box<CompiledFilter>),
24}
25
26pub fn compile_filter(filter: &ast::Filter) -> Result<CompiledFilter> {
28 match filter {
29 ast::Filter::Eq(f, v) => Ok(CompiledFilter::Eq(f.clone(), v.clone())),
30 ast::Filter::Ne(f, v) => Ok(CompiledFilter::Ne(f.clone(), v.clone())),
31 ast::Filter::Gt(f, v) => Ok(CompiledFilter::Gt(f.clone(), v.clone())),
32 ast::Filter::Gte(f, v) => Ok(CompiledFilter::Gte(f.clone(), v.clone())),
33 ast::Filter::Lt(f, v) => Ok(CompiledFilter::Lt(f.clone(), v.clone())),
34 ast::Filter::Lte(f, v) => Ok(CompiledFilter::Lte(f.clone(), v.clone())),
35 ast::Filter::In(f, v) => Ok(CompiledFilter::In(f.clone(), v.clone())),
36 ast::Filter::NotIn(f, v) => Ok(CompiledFilter::NotIn(f.clone(), v.clone())),
37 ast::Filter::Contains(f, v) => Ok(CompiledFilter::Contains(f.clone(), v.clone())),
38 ast::Filter::StartsWith(f, v) => Ok(CompiledFilter::StartsWith(f.clone(), v.clone())),
39 ast::Filter::EndsWith(f, v) => Ok(CompiledFilter::EndsWith(f.clone(), v.clone())),
40 ast::Filter::Matches(f, v) => {
41 if let ast::Value::String(pattern) = v {
42 let re = regex::RegexBuilder::new(pattern)
44 .size_limit(10_000_000) .dfa_size_limit(2_000_000) .build()
47 .map_err(|e| {
48 AqlError::new(
49 ErrorCode::SecurityError,
50 format!(
51 "Regex pattern '{}' is too complex or invalid: {}",
52 pattern, e
53 ),
54 )
55 })?;
56 Ok(CompiledFilter::Matches(f.clone(), re))
57 } else {
58 Err(AqlError::new(
59 ErrorCode::InvalidInput,
60 "Matches filter requires a string pattern",
61 ))
62 }
63 }
64 ast::Filter::IsNull(f) => Ok(CompiledFilter::IsNull(f.clone())),
65 ast::Filter::IsNotNull(f) => Ok(CompiledFilter::IsNotNull(f.clone())),
66 ast::Filter::And(filters) => {
67 let compiled = filters
68 .iter()
69 .map(compile_filter)
70 .collect::<Result<Vec<_>>>()?;
71 Ok(CompiledFilter::And(compiled))
72 }
73 ast::Filter::Or(filters) => {
74 let compiled = filters
75 .iter()
76 .map(compile_filter)
77 .collect::<Result<Vec<_>>>()?;
78 Ok(CompiledFilter::Or(compiled))
79 }
80 ast::Filter::Not(filter) => {
81 let compiled = compile_filter(filter)?;
82 Ok(CompiledFilter::Not(Box::new(compiled)))
83 }
84 }
85}