Skip to content

Commit cbe3fb2

Browse files
authored
fix(query): avoid eliminating aggregate union branch (#19987)
1 parent 1d3095e commit cbe3fb2

2 files changed

Lines changed: 53 additions & 3 deletions

File tree

src/query/sql/src/planner/optimizer/optimizers/rule/union_rules/rule_eliminate_union.rs

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,20 @@ impl RuleEliminateUnion {
5555
return Ok(false);
5656
}
5757
if child_num == 0 {
58-
Ok(matches!(
58+
return Ok(matches!(
5959
s_expr.plan(),
6060
RelOperator::ConstantTableScan(ConstantTableScan { num_rows: 0, .. })
61-
))
62-
} else {
61+
));
62+
}
63+
64+
// Only pass through unary operators that preserve empty input as empty output.
65+
if matches!(
66+
s_expr.plan().rel_op(),
67+
RelOp::Filter | RelOp::EvalScalar | RelOp::Sort | RelOp::Limit | RelOp::Exchange
68+
) {
6369
Self::is_empty_scan(s_expr.child(0)?)
70+
} else {
71+
Ok(false)
6472
}
6573
}
6674
}
@@ -122,3 +130,35 @@ impl Rule for RuleEliminateUnion {
122130
&self.matchers
123131
}
124132
}
133+
134+
#[cfg(test)]
135+
mod tests {
136+
use std::collections::BTreeSet;
137+
138+
use super::*;
139+
use crate::plans::Aggregate;
140+
use crate::plans::Filter;
141+
142+
fn empty_scan_expr() -> SExpr {
143+
let empty_scan =
144+
ConstantTableScan::new_empty_scan(DataSchemaRefExt::create(vec![]), BTreeSet::new());
145+
SExpr::create_leaf(Arc::new(RelOperator::ConstantTableScan(empty_scan)))
146+
}
147+
148+
#[test]
149+
fn only_empty_preserving_unary_nodes_are_transparent() -> Result<()> {
150+
let filter = SExpr::create_unary(
151+
Arc::new(RelOperator::Filter(Filter { predicates: vec![] })),
152+
Arc::new(empty_scan_expr()),
153+
);
154+
assert!(RuleEliminateUnion::is_empty_scan(&filter)?);
155+
156+
let aggregate = SExpr::create_unary(
157+
Arc::new(RelOperator::Aggregate(Aggregate::default())),
158+
Arc::new(empty_scan_expr()),
159+
);
160+
assert!(!RuleEliminateUnion::is_empty_scan(&aggregate)?);
161+
162+
Ok(())
163+
}
164+
}

tests/sqllogictests/suites/query/union.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,16 @@ select 1 as c union all select 3.3::Double;
173173
1.0
174174
3.3
175175

176+
query I
177+
SELECT x FROM (
178+
SELECT 1 AS x
179+
UNION ALL
180+
SELECT count(*) AS x FROM (SELECT * FROM numbers(1) WHERE false)
181+
) ORDER BY x
182+
----
183+
0
184+
1
185+
176186
query I
177187
with
178188
t1 as (select number as a from numbers(10)),

0 commit comments

Comments
 (0)