Skip to content

Commit 9f0a01f

Browse files
committed
fix(query): preserve nullable self-equality filters
1 parent f3d33f1 commit 9f0a01f

4 files changed

Lines changed: 36 additions & 2 deletions

File tree

src/query/sql/src/planner/optimizer/optimizers/operator/filter/infer_filter.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,12 @@ impl<'a> InferFilterOptimizer<'a> {
189189
}
190190

191191
pub fn add_equal_expr(&mut self, left: &ScalarExpr, right: &ScalarExpr) -> bool {
192+
if left == right {
193+
// Under SQL three-valued logic, NULL = NULL is NULL rather than TRUE. Only
194+
// absorb a reflexive equality when its operand is guaranteed to be non-null.
195+
return !left.data_type().is_nullable_or_null();
196+
}
197+
192198
let left_ty = left.data_type();
193199
let right_ty = right.data_type();
194200
if !common_super_type_with_conversion(left_ty.as_ref(), right_ty.as_ref())

src/query/sql/test-support/data/results/tpcds/Q01_optimized.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ TopN
5656
│ │ │ │ └── limit: NONE
5757
│ │ │ └── Scan
5858
│ │ │ ├── table: default.store_returns (#4)
59-
│ │ │ ├── filters: []
59+
│ │ │ ├── filters: [eq(store_returns.sr_store_sk (#103), store_returns.sr_store_sk (#103))]
6060
│ │ │ ├── order by: []
6161
│ │ │ └── limit: NONE
6262
│ │ └── Scan

src/query/sql/test-support/data/results/tpcds/Q01_physical.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ TopN(Final)
111111
│ │ │ ├── read size: 0
112112
│ │ │ ├── partitions total: 0
113113
│ │ │ ├── partitions scanned: 0
114-
│ │ │ ├── push downs: [filters: [], limit: NONE]
114+
│ │ │ ├── push downs: [filters: [is_true(store_returns.sr_store_sk (#103) = store_returns.sr_store_sk (#103))], limit: NONE]
115115
│ │ │ ├── apply join filters: [#1]
116116
│ │ │ └── estimated rows: 0.00
117117
│ │ └── TableScan(Probe)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# GitHub issue: https://github.com/databendlabs/databend/issues/20379
2+
# Reflexive equality is not a tautology for nullable operands because NULL = NULL is NULL.
3+
4+
statement ok
5+
DROP TABLE IF EXISTS issue_20379_reflexive_equality
6+
7+
statement ok
8+
CREATE TABLE issue_20379_reflexive_equality(c TIMESTAMP NULL)
9+
10+
statement ok
11+
INSERT INTO issue_20379_reflexive_equality VALUES
12+
('2020-01-01 10:00:00'),
13+
('2020-05-05 08:30:00'),
14+
(NULL)
15+
16+
# The all-NULL group must not pass HAVING.
17+
query I
18+
SELECT count(*) FROM (
19+
SELECT c
20+
FROM issue_20379_reflexive_equality
21+
GROUP BY c
22+
HAVING min(c) = min(c)
23+
)
24+
----
25+
2
26+
27+
statement ok
28+
DROP TABLE issue_20379_reflexive_equality

0 commit comments

Comments
 (0)