Skip to main content

cynos_query/executor/
filter.rs

1//! Filter executor.
2
3use crate::ast::Predicate;
4use crate::executor::{Relation, RelationEntry};
5use alloc::vec::Vec;
6
7/// Filter executor - filters rows based on a predicate.
8pub struct FilterExecutor<P: Predicate> {
9    predicate: P,
10}
11
12impl<P: Predicate> FilterExecutor<P> {
13    /// Creates a new filter executor.
14    pub fn new(predicate: P) -> Self {
15        Self { predicate }
16    }
17
18    /// Executes the filter on the input relation.
19    pub fn execute(&self, input: Relation) -> Relation {
20        let tables = input.tables().to_vec();
21        let table_column_counts = input.table_column_counts().to_vec();
22        let entries: Vec<RelationEntry> = input
23            .into_iter()
24            .filter(|entry| self.predicate.eval(&entry.row))
25            .collect();
26
27        Relation { entries, tables, table_column_counts }
28    }
29}
30
31/// Filters a relation using a closure.
32#[allow(dead_code)]
33pub fn filter_relation<F>(input: Relation, predicate: F) -> Relation
34where
35    F: Fn(&RelationEntry) -> bool,
36{
37    let tables = input.tables().to_vec();
38    let table_column_counts = input.table_column_counts().to_vec();
39    let entries: Vec<RelationEntry> = input.into_iter().filter(|e| predicate(e)).collect();
40
41    Relation { entries, tables, table_column_counts }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use crate::ast::{ColumnRef, EvalType, ValuePredicate};
48    use alloc::vec;
49    use cynos_core::{Row, Value};
50
51    #[test]
52    fn test_filter_executor() {
53        let rows = vec![
54            Row::new(1, vec![Value::Int64(10)]),
55            Row::new(2, vec![Value::Int64(20)]),
56            Row::new(3, vec![Value::Int64(30)]),
57        ];
58        let input = Relation::from_rows_owned(rows, vec!["t".into()]);
59
60        let col = ColumnRef::new("t", "value", 0);
61        let pred = ValuePredicate::new(col, EvalType::Gt, Value::Int64(15));
62        let executor = FilterExecutor::new(pred);
63
64        let result = executor.execute(input);
65        assert_eq!(result.len(), 2);
66    }
67
68    #[test]
69    fn test_filter_relation_closure() {
70        let rows = vec![
71            Row::new(1, vec![Value::Int64(10)]),
72            Row::new(2, vec![Value::Int64(20)]),
73        ];
74        let input = Relation::from_rows_owned(rows, vec!["t".into()]);
75
76        let result = filter_relation(input, |entry| {
77            entry
78                .get_field(0)
79                .and_then(|v| v.as_i64())
80                .map(|v| v > 15)
81                .unwrap_or(false)
82        });
83
84        assert_eq!(result.len(), 1);
85    }
86}