Skip to content

Commit a9a6630

Browse files
authored
feat: add limit push down rule (#16403)
* feat: add limit push down rule * fix * fix test
1 parent dd21d7d commit a9a6630

File tree

6 files changed

+108
-0
lines changed

6 files changed

+108
-0
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/query/sql/src/planner/optimizer/rule/factory.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::optimizer::rule::rewrite::RulePushDownFilterProjectSet;
3434
use crate::optimizer::rule::rewrite::RulePushDownFilterScan;
3535
use crate::optimizer::rule::rewrite::RulePushDownFilterSort;
3636
use crate::optimizer::rule::rewrite::RulePushDownFilterUnion;
37+
use crate::optimizer::rule::rewrite::RulePushDownLimit;
3738
use crate::optimizer::rule::rewrite::RulePushDownLimitOuterJoin;
3839
use crate::optimizer::rule::rewrite::RulePushDownLimitScan;
3940
use crate::optimizer::rule::rewrite::RulePushDownLimitSort;
@@ -63,6 +64,7 @@ impl RuleFactory {
6364
RuleID::PushDownFilterScan => Ok(Box::new(RulePushDownFilterScan::new(metadata))),
6465
RuleID::PushDownFilterSort => Ok(Box::new(RulePushDownFilterSort::new())),
6566
RuleID::PushDownFilterProjectSet => Ok(Box::new(RulePushDownFilterProjectSet::new())),
67+
RuleID::PushDownLimit => Ok(Box::new(RulePushDownLimit::new(metadata))),
6668
RuleID::PushDownLimitUnion => Ok(Box::new(RulePushDownLimitUnion::new())),
6769
RuleID::PushDownLimitScan => Ok(Box::new(RulePushDownLimitScan::new())),
6870
RuleID::PushDownSortScan => Ok(Box::new(RulePushDownSortScan::new())),

src/query/sql/src/planner/optimizer/rule/rewrite/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod rule_push_down_filter_scan;
3030
mod rule_push_down_filter_sort;
3131
mod rule_push_down_filter_union;
3232
mod rule_push_down_filter_window;
33+
mod rule_push_down_limit;
3334
mod rule_push_down_limit_aggregate;
3435
mod rule_push_down_limit_expression;
3536
mod rule_push_down_limit_join;
@@ -60,6 +61,7 @@ pub use rule_push_down_filter_scan::RulePushDownFilterScan;
6061
pub use rule_push_down_filter_sort::RulePushDownFilterSort;
6162
pub use rule_push_down_filter_union::RulePushDownFilterUnion;
6263
pub use rule_push_down_filter_window::RulePushDownFilterWindow;
64+
pub use rule_push_down_limit::RulePushDownLimit;
6365
pub use rule_push_down_limit_aggregate::RulePushDownLimitAggregate;
6466
pub use rule_push_down_limit_expression::RulePushDownLimitEvalScalar;
6567
pub use rule_push_down_limit_join::RulePushDownLimitOuterJoin;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright 2021 Datafuse Labs
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use std::sync::Arc;
16+
17+
use databend_common_exception::Result;
18+
use databend_common_expression::Column;
19+
use databend_common_expression::DataField;
20+
use databend_common_expression::DataSchemaRefExt;
21+
22+
use crate::optimizer::extract::Matcher;
23+
use crate::optimizer::rule::Rule;
24+
use crate::optimizer::rule::TransformResult;
25+
use crate::optimizer::RelExpr;
26+
use crate::optimizer::RuleID;
27+
use crate::optimizer::SExpr;
28+
use crate::plans::ConstantTableScan;
29+
use crate::plans::Limit;
30+
use crate::plans::Operator;
31+
use crate::plans::RelOp;
32+
use crate::plans::RelOperator;
33+
use crate::MetadataRef;
34+
35+
pub struct RulePushDownLimit {
36+
id: RuleID,
37+
metadata: MetadataRef,
38+
matchers: Vec<Matcher>,
39+
}
40+
41+
impl RulePushDownLimit {
42+
pub fn new(metadata: MetadataRef) -> Self {
43+
Self {
44+
id: RuleID::PushDownLimit,
45+
metadata,
46+
matchers: vec![Matcher::MatchOp {
47+
op_type: RelOp::Limit,
48+
children: vec![Matcher::Leaf],
49+
}],
50+
}
51+
}
52+
}
53+
54+
impl Rule for RulePushDownLimit {
55+
fn id(&self) -> RuleID {
56+
self.id
57+
}
58+
59+
fn apply(&self, s_expr: &SExpr, state: &mut TransformResult) -> Result<()> {
60+
let limit: Limit = s_expr.plan().clone().try_into()?;
61+
if let Some(limit_val) = limit.limit
62+
&& limit_val == 0
63+
{
64+
let output_columns = limit
65+
.derive_relational_prop(&RelExpr::with_s_expr(s_expr))?
66+
.output_columns
67+
.clone();
68+
let metadata = self.metadata.read();
69+
let mut fields = Vec::with_capacity(output_columns.len());
70+
for col in output_columns.iter() {
71+
fields.push(DataField::new(
72+
&col.to_string(),
73+
metadata.column(*col).data_type(),
74+
));
75+
}
76+
let empty_scan = ConstantTableScan {
77+
values: vec![Column::Null { len: 0 }; output_columns.len()],
78+
num_rows: 0,
79+
schema: DataSchemaRefExt::create(fields),
80+
columns: output_columns,
81+
};
82+
let result = SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan)));
83+
state.add_result(result);
84+
}
85+
86+
Ok(())
87+
}
88+
89+
fn matchers(&self) -> &[Matcher] {
90+
&self.matchers
91+
}
92+
}

src/query/sql/src/planner/optimizer/rule/rule.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub static DEFAULT_REWRITE_RULES: LazyLock<Vec<RuleID>> = LazyLock::new(|| {
3434
RuleID::PushDownFilterUnion,
3535
RuleID::PushDownFilterAggregate,
3636
RuleID::PushDownFilterWindow,
37+
RuleID::PushDownLimit,
3738
RuleID::PushDownLimitUnion,
3839
RuleID::PushDownLimitEvalScalar,
3940
RuleID::PushDownLimitSort,
@@ -83,6 +84,7 @@ pub enum RuleID {
8384
PushDownFilterSort,
8485
PushDownFilterProjectSet,
8586
PushDownFilterWindow,
87+
PushDownLimit,
8688
PushDownLimitUnion,
8789
PushDownLimitOuterJoin,
8890
PushDownLimitEvalScalar,
@@ -118,6 +120,7 @@ impl Display for RuleID {
118120
RuleID::PushDownFilterScan => write!(f, "PushDownFilterScan"),
119121
RuleID::PushDownFilterSort => write!(f, "PushDownFilterSort"),
120122
RuleID::PushDownFilterProjectSet => write!(f, "PushDownFilterProjectSet"),
123+
RuleID::PushDownLimit => write!(f, "PushDownLimit"),
121124
RuleID::PushDownLimitUnion => write!(f, "PushDownLimitUnion"),
122125
RuleID::PushDownLimitOuterJoin => write!(f, "PushDownLimitOuterJoin"),
123126
RuleID::PushDownLimitEvalScalar => write!(f, "PushDownLimitEvalScalar"),

tests/sqllogictests/suites/mode/standalone/explain/limit.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,11 @@ Limit
220220
├── partitions scanned: 1
221221
├── push downs: [filters: [], limit: NONE]
222222
└── estimated rows: 2.00
223+
224+
225+
query T
226+
explain select c1 from (select count(t1.number) as c1 from numbers(1) as t1 group by number) as t3 left join (select count(t.number) as c from numbers(2) as t group by number) as t4 on t3.c1=t4.c order by t3.c1 limit 0
227+
----
228+
ConstantTableScan
229+
├── output columns: [count(t1.number) (#2)]
230+
└── column 0: []

0 commit comments

Comments
 (0)