Skip to content

Commit fcbf36f

Browse files
committed
fix: return optional timestamp range
1 parent ddf0540 commit fcbf36f

File tree

1 file changed

+46
-35
lines changed

1 file changed

+46
-35
lines changed

src/table/src/predicate.rs

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use common_query::logical_plan::{DfExpr, Expr};
1616
use common_telemetry::{error, warn};
17-
use common_time::range::{GenericRange, TimestampRange};
17+
use common_time::range::TimestampRange;
1818
use common_time::Timestamp;
1919
use datafusion::parquet::file::metadata::RowGroupMetaData;
2020
use datafusion::physical_optimizer::pruning::PruningPredicate;
@@ -88,13 +88,17 @@ impl<'a> TimeRangePredicateBuilder<'a> {
8888
pub fn build(&self) -> TimestampRange {
8989
let mut res = TimestampRange::min_to_max();
9090
for expr in self.filters {
91-
let range = self.extract_time_range_from_expr(expr.df_expr());
91+
let range = self
92+
.extract_time_range_from_expr(expr.df_expr())
93+
.unwrap_or_else(TimestampRange::min_to_max);
9294
res = res.and(&range);
9395
}
9496
res
9597
}
9698

97-
fn extract_time_range_from_expr(&self, expr: &DfExpr) -> TimestampRange {
99+
/// Extract time range filter from `WHERE`/`IN (...)`/`BETWEEN` clauses.
100+
/// Return None if no time range can be found in expr.
101+
fn extract_time_range_from_expr(&self, expr: &DfExpr) -> Option<TimestampRange> {
98102
match expr {
99103
DfExpr::BinaryExpr(BinaryExpr { left, op, right }) => {
100104
self.extract_from_binary_expr(left, op, right)
@@ -110,7 +114,7 @@ impl<'a> TimeRangePredicateBuilder<'a> {
110114
list,
111115
negated,
112116
} => self.extract_from_in_list_expr(expr, *negated, list),
113-
_ => TimestampRange::min_to_max(),
117+
_ => None,
114118
}
115119
}
116120

@@ -119,34 +123,40 @@ impl<'a> TimeRangePredicateBuilder<'a> {
119123
left: &DfExpr,
120124
op: &Operator,
121125
right: &DfExpr,
122-
) -> GenericRange<Timestamp> {
126+
) -> Option<TimestampRange> {
123127
match op {
124128
Operator::Eq => self
125129
.get_timestamp_filter(left, right)
126-
.map(TimestampRange::single)
127-
.unwrap_or_else(TimestampRange::min_to_max),
130+
.map(TimestampRange::single),
128131
Operator::Lt => self
129132
.get_timestamp_filter(left, right)
130-
.map(|ts| TimestampRange::until_end(ts, false))
131-
.unwrap_or_else(TimestampRange::min_to_max),
133+
.map(|ts| TimestampRange::until_end(ts, false)),
132134
Operator::LtEq => self
133135
.get_timestamp_filter(left, right)
134-
.map(|ts| TimestampRange::until_end(ts, true))
135-
.unwrap_or_else(TimestampRange::min_to_max),
136+
.map(|ts| TimestampRange::until_end(ts, true)),
136137
Operator::Gt => self
137138
.get_timestamp_filter(left, right)
138-
.map(TimestampRange::from_start)
139-
.unwrap_or_else(TimestampRange::min_to_max),
139+
.map(TimestampRange::from_start),
140140
Operator::GtEq => self
141141
.get_timestamp_filter(left, right)
142-
.map(TimestampRange::from_start)
143-
.unwrap_or_else(TimestampRange::min_to_max),
144-
Operator::And => self
145-
.extract_time_range_from_expr(left)
146-
.and(&self.extract_time_range_from_expr(right)),
147-
Operator::Or => self
148-
.extract_time_range_from_expr(left)
149-
.or(&self.extract_time_range_from_expr(right)),
142+
.map(TimestampRange::from_start),
143+
Operator::And => {
144+
// instead of return none when failed to extract time range from left/right, we unwrap the none into
145+
// `TimestampRange::min_to_max`.
146+
let left = self
147+
.extract_time_range_from_expr(left)
148+
.unwrap_or_else(TimestampRange::min_to_max);
149+
let right = self
150+
.extract_time_range_from_expr(right)
151+
.unwrap_or_else(TimestampRange::min_to_max);
152+
Some(left.and(&right))
153+
}
154+
Operator::Or => {
155+
let Some(left) = self
156+
.extract_time_range_from_expr(left) else { return None };
157+
let Some(right) = self.extract_time_range_from_expr(right) else { return None };
158+
Some(left.or(&right))
159+
}
150160
Operator::NotEq
151161
| Operator::Plus
152162
| Operator::Minus
@@ -168,7 +178,7 @@ impl<'a> TimeRangePredicateBuilder<'a> {
168178
| Operator::BitwiseXor
169179
| Operator::BitwiseShiftRight
170180
| Operator::BitwiseShiftLeft
171-
| Operator::StringConcat => TimestampRange::min_to_max(),
181+
| Operator::StringConcat => None,
172182
}
173183
}
174184

@@ -192,42 +202,43 @@ impl<'a> TimeRangePredicateBuilder<'a> {
192202
negated: &bool,
193203
low: &DfExpr,
194204
high: &DfExpr,
195-
) -> GenericRange<Timestamp> {
196-
let DfExpr::Column(col) = expr else { return TimestampRange::min_to_max(); };
205+
) -> Option<TimestampRange> {
206+
let DfExpr::Column(col) = expr else { return None; };
197207
if col.name != self.ts_col_name {
198-
return TimestampRange::min_to_max();
208+
return None;
199209
}
200210

201211
if *negated {
202-
return TimestampRange::min_to_max();
212+
return None;
203213
}
204214

205215
match (low, high) {
206216
(DfExpr::Literal(low), DfExpr::Literal(high)) => {
207217
let low_opt = scalar_value_to_timestamp(low);
208218
let high_opt = scalar_value_to_timestamp(high);
209-
TimestampRange::new_inclusive(low_opt, high_opt)
219+
Some(TimestampRange::new_inclusive(low_opt, high_opt))
210220
}
211-
_ => TimestampRange::min_to_max(),
221+
_ => None,
212222
}
213223
}
214224

225+
/// Extract time range filter from `IN (...)` expr.
215226
fn extract_from_in_list_expr(
216227
&self,
217228
expr: &DfExpr,
218229
negated: bool,
219230
list: &[DfExpr],
220-
) -> GenericRange<Timestamp> {
231+
) -> Option<TimestampRange> {
221232
if negated {
222-
return TimestampRange::min_to_max();
233+
return None;
223234
}
224-
let DfExpr::Column(col) = expr else { return TimestampRange::min_to_max(); };
235+
let DfExpr::Column(col) = expr else { return None; };
225236
if col.name != self.ts_col_name {
226-
return TimestampRange::min_to_max();
237+
return None;
227238
}
228239

229240
if list.is_empty() {
230-
return TimestampRange::empty();
241+
return Some(TimestampRange::empty());
231242
}
232243
let mut init = TimestampRange::empty();
233244
for expr in list {
@@ -237,11 +248,11 @@ impl<'a> TimeRangePredicateBuilder<'a> {
237248
} else {
238249
// TODO(hl): maybe we should raise an error here since cannot parse
239250
// timestamp value from in list expr
240-
return TimestampRange::min_to_max();
251+
return None;
241252
}
242253
}
243254
}
244-
init
255+
Some(init)
245256
}
246257
}
247258

0 commit comments

Comments
 (0)