@@ -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