dbx_core/sql/optimizer/
limit_pushdown.rs1use crate::error::DbxResult;
6use crate::sql::planner::LogicalPlan;
7
8use super::OptimizationRule;
9
10pub struct LimitPushdownRule;
12
13impl OptimizationRule for LimitPushdownRule {
14 fn name(&self) -> &str {
15 "LimitPushdown"
16 }
17
18 fn apply(&self, plan: LogicalPlan) -> DbxResult<LogicalPlan> {
19 self.push_down(plan)
20 }
21}
22
23impl LimitPushdownRule {
24 fn push_down(&self, plan: LogicalPlan) -> DbxResult<LogicalPlan> {
25 match plan {
26 LogicalPlan::Limit {
27 input,
28 count,
29 offset,
30 } => {
31 let optimized_input = self.push_down(*input)?;
32 match optimized_input {
33 LogicalPlan::Project {
34 input: project_input,
35 projections: columns,
36 } if offset == 0 => {
37 let pushed = LogicalPlan::Limit {
38 input: project_input,
39 count,
40 offset: 0,
41 };
42 Ok(LogicalPlan::Project {
43 input: Box::new(pushed),
44 projections: columns,
45 })
46 }
47 LogicalPlan::Limit {
48 input: inner_input,
49 count: inner_count,
50 offset: inner_offset,
51 } => {
52 let final_count = count.min(inner_count);
53 let final_offset = offset + inner_offset;
54 Ok(LogicalPlan::Limit {
55 input: inner_input,
56 count: final_count,
57 offset: final_offset,
58 })
59 }
60 other => Ok(LogicalPlan::Limit {
61 input: Box::new(other),
62 count,
63 offset,
64 }),
65 }
66 }
67 LogicalPlan::Project {
68 input,
69 projections: columns,
70 } => Ok(LogicalPlan::Project {
71 input: Box::new(self.push_down(*input)?),
72 projections: columns,
73 }),
74 LogicalPlan::Filter { input, predicate } => Ok(LogicalPlan::Filter {
75 input: Box::new(self.push_down(*input)?),
76 predicate,
77 }),
78 LogicalPlan::Sort { input, order_by } => Ok(LogicalPlan::Sort {
79 input: Box::new(self.push_down(*input)?),
80 order_by,
81 }),
82 LogicalPlan::Aggregate {
83 input,
84 group_by,
85 aggregates,
86 } => Ok(LogicalPlan::Aggregate {
87 input: Box::new(self.push_down(*input)?),
88 group_by,
89 aggregates,
90 }),
91 other => Ok(other),
92 }
93 }
94}