Skip to content

Commit 4d8fe1a

Browse files
committed
fix
1 parent 608f08a commit 4d8fe1a

3 files changed

Lines changed: 14 additions & 3 deletions

File tree

src/query/sql/src/planner/plans/union_all.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ impl UnionAll {
133133
{
134134
return Ok(Some((output, right)));
135135
}
136+
// TODO: Distinguish all-NULL column statistics from unknown statistics so
137+
// a non-empty all-NULL branch can contribute its NULL count without
138+
// discarding the other branch's value statistics.
136139
_ => return Ok(None),
137140
};
138141
let mut ndv = Self::merge_ndv(&left, &right)?;
@@ -179,6 +182,14 @@ impl UnionAll {
179182

180183
fn merge_ndv(left: &ColumnStat, right: &ColumnStat) -> Result<NdvEstimate> {
181184
let ndv_upper = left.ndv.upper + right.ndv.upper;
185+
let ranges_disjoint = left.max.compare(&right.min)? == Ordering::Less
186+
|| right.max.compare(&left.min)? == Ordering::Less;
187+
if ranges_disjoint
188+
&& let (Some(left), Some(right)) = (left.ndv.expected, right.ndv.expected)
189+
{
190+
return Ok(NdvEstimate::new(left + right, ndv_upper));
191+
}
192+
182193
if left.min.is_numeric()
183194
&& let (Some(left), Some(left_ndv)) = (&left.histogram, left.ndv.expected)
184195
&& let (Some(right), Some(right_ndv)) = (&right.histogram, right.ndv.expected)

src/query/sql/tests/it/optimizer/union_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ fn cases() -> Result<Vec<UnionCase>> {
261261
Ok(vec![
262262
UnionCase {
263263
name: "lossless_coercion",
264-
description: "SQL binding inserts a nullable INT to BIGINT coercion and UnionAll derives statistics after the cast.",
264+
description: "SQL binding inserts a nullable INT to BIGINT coercion; after the cast drops the histogram, disjoint ranges still make the union NDV additive.",
265265
sql: "SELECT k FROM l UNION ALL SELECT k FROM r",
266266
tables: vec![
267267
table(

src/query/sql/tests/it/optimizer/union_all.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
=== lossless_coercion ===
2-
description: SQL binding inserts a nullable INT to BIGINT coercion and UnionAll derives statistics after the cast.
2+
description: SQL binding inserts a nullable INT to BIGINT coercion; after the cast drops the histogram, disjoint ranges still make the union NDV additive.
33
sql: SELECT k FROM l UNION ALL SELECT k FROM r
44
path: []
55
node:
@@ -22,7 +22,7 @@ UnionAll
2222

2323
cardinality: 30.000
2424
precise_cardinality: Some(30)
25-
column_stat: k (#2) min=1, max=8, ndv=~5.0[..8.0], null_count=3, histogram=none
25+
column_stat: k (#2) min=1, max=8, ndv=8.0, null_count=3, histogram=none
2626

2727
=== finite_range_reduces_union_ndv_bound ===
2828
description: UnionAll reduces its conservative NDV upper bound to the merged finite range before an outer cast consumes the statistics.

0 commit comments

Comments
 (0)