uqa_execution/relational/
filter.rs1use super::{
10 truthy, Batch, DefaultExpressionEvaluator, ExecResult, PhysicalOperator, RowSchema, SQLParam,
11 ScalarExpr, SharedExpressionEvaluator, SharedRowPredicate,
12};
13
14pub struct Filter<'a> {
17 child: Box<dyn PhysicalOperator + 'a>,
18 condition: FilterCondition<'a>,
19 schema: RowSchema,
20}
21
22enum FilterCondition<'a> {
23 Expression {
24 predicate: ScalarExpr,
25 evaluator: SharedExpressionEvaluator<'a>,
26 },
27 Row(SharedRowPredicate<'a>),
28}
29
30impl Filter<'static> {
31 pub fn new(
32 child: Box<dyn PhysicalOperator>,
33 predicate: ScalarExpr,
34 params: Vec<SQLParam>,
35 ) -> Self {
36 Self::with_evaluator(child, predicate, DefaultExpressionEvaluator::shared(params))
37 }
38}
39
40impl<'a> Filter<'a> {
41 pub fn with_evaluator(
42 child: Box<dyn PhysicalOperator + 'a>,
43 predicate: ScalarExpr,
44 evaluator: SharedExpressionEvaluator<'a>,
45 ) -> Self {
46 let schema = child.row_schema().clone();
47 let predicate = crate::bind_type_introspection(predicate, &schema, evaluator.parameters());
48 Self {
49 child,
50 condition: FilterCondition::Expression {
51 predicate,
52 evaluator,
53 },
54 schema,
55 }
56 }
57
58 pub fn with_row_predicate(
59 child: Box<dyn PhysicalOperator + 'a>,
60 predicate: SharedRowPredicate<'a>,
61 ) -> Self {
62 let schema = child.row_schema().clone();
63 Self {
64 child,
65 condition: FilterCondition::Row(predicate),
66 schema,
67 }
68 }
69}
70
71impl PhysicalOperator for Filter<'_> {
72 fn row_schema(&self) -> &RowSchema {
73 &self.schema
74 }
75
76 fn estimated_cardinality(&self) -> Option<u64> {
77 self.child.estimated_cardinality()
78 }
79
80 fn output_ordering(&self) -> &[crate::PhysicalOrder] {
81 self.child.output_ordering()
82 }
83
84 fn open(&mut self) -> ExecResult<()> {
85 self.child.open()
86 }
87
88 fn next(&mut self) -> ExecResult<Option<Batch>> {
89 loop {
90 let Some(batch) = self.child.next()? else {
91 return Ok(None);
92 };
93 let mut kept = Vec::with_capacity(batch.rows.len());
94 for row in batch.rows {
95 let keep = match &self.condition {
96 FilterCondition::Expression {
97 predicate,
98 evaluator,
99 } => truthy(&evaluator.evaluate_physical(predicate, &batch.schema, &row)?),
100 FilterCondition::Row(predicate) => {
101 predicate.keep_physical(&batch.schema, &row)?
102 }
103 };
104 if keep {
105 kept.push(row);
106 }
107 }
108 if !kept.is_empty() {
109 return Ok(Some(Batch::from_physical_rows(self.schema.clone(), kept)));
110 }
111 }
112 }
113
114 fn close(&mut self) -> ExecResult<()> {
115 self.child.close()
116 }
117}