Skip to content

Commit 4539acf

Browse files
xudong963Friede80
andauthored
prevent rewriting strict inequality to closed interval for non-discrete types (#21) (#108)
Co-authored-by: Matt Friede <[email protected]>
1 parent 9c91580 commit 4539acf

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

src/rewrite/normal_form.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -527,8 +527,8 @@ impl Predicate {
527527
// so handling of open intervals is done by adding/subtracting the smallest increment.
528528
// However, there is not really a public API to do this,
529529
// other than the satisfy_greater method.
530-
Operator::Lt => Ok(
531-
match satisfy_greater(
530+
Operator::Lt => {
531+
let range_val = match satisfy_greater(
532532
&Interval::try_new(value.clone(), value.clone())?,
533533
&Interval::make_unbounded(&value.data_type())?,
534534
true,
@@ -538,11 +538,19 @@ impl Predicate {
538538
*range = None;
539539
return Ok(());
540540
}
541-
},
542-
),
543-
// Same thing as above.
544-
Operator::Gt => Ok(
545-
match satisfy_greater(
541+
};
542+
// If the type is not discrete (e.g. Utf8), satisfy_greater may return an unchanged value.
543+
// This means the interval could not be tightened and it is unsafe to produce a closed interval
544+
if range_val.upper() == &value {
545+
Err(DataFusionError::Plan(
546+
"cannot represent strict inequality as closed interval for non-discrete types".to_string(),
547+
))
548+
} else {
549+
Ok(range_val)
550+
}
551+
}
552+
Operator::Gt => {
553+
let range_val = match satisfy_greater(
546554
&Interval::make_unbounded(&value.data_type())?,
547555
&Interval::try_new(value.clone(), value.clone())?,
548556
true,
@@ -552,8 +560,15 @@ impl Predicate {
552560
*range = None;
553561
return Ok(());
554562
}
555-
},
556-
),
563+
};
564+
if range_val.lower() == &value {
565+
Err(DataFusionError::Plan(
566+
"cannot represent strict inequality as closed interval for non-discrete types".to_string(),
567+
))
568+
} else {
569+
Ok(range_val)
570+
}
571+
}
557572
_ => Err(DataFusionError::Plan(
558573
"unsupported binary expression".to_string(),
559574
)),
@@ -1154,6 +1169,11 @@ mod test {
11541169
// we are allowed to substitute column1 for column3 and vice versa.
11551170
"SELECT column2, column3 FROM t1 WHERE column1 = column3 AND column3 >= '2023'",
11561171
},
1172+
TestCase {
1173+
name: "range filter with inequality on non-discrete type",
1174+
base: "SELECT * FROM t1",
1175+
query: "SELECT column1 FROM t1 WHERE column1 < '2022'",
1176+
},
11571177
TestCase {
11581178
name: "duplicate expressions (X-209)",
11591179
base: "SELECT * FROM t1",

0 commit comments

Comments
 (0)