Skip to content

Commit b9bf6c9

Browse files
authored
Fix Duration vs Interval comparisons and Interval as LHS (#11876)
* fix duration vs. interval and interval as LHS * add more operators to "interval vs. duration comparison" slt tests
1 parent 0ce6d16 commit b9bf6c9

File tree

4 files changed

+102
-1
lines changed

4 files changed

+102
-1
lines changed

datafusion/expr/src/type_coercion/binary.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,9 @@ fn temporal_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option<DataTyp
11301130
use arrow::datatypes::TimeUnit::*;
11311131

11321132
match (lhs_type, rhs_type) {
1133-
(Interval(_), Interval(_)) => Some(Interval(MonthDayNano)),
1133+
(Interval(_) | Duration(_), Interval(_) | Duration(_)) => {
1134+
Some(Interval(MonthDayNano))
1135+
}
11341136
(Date64, Date32) | (Date32, Date64) => Some(Date64),
11351137
(Timestamp(_, None), Date64) | (Date64, Timestamp(_, None)) => {
11361138
Some(Timestamp(Nanosecond, None))

datafusion/sql/src/expr/value.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,12 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
227227
let df_op = match op {
228228
BinaryOperator::Plus => Operator::Plus,
229229
BinaryOperator::Minus => Operator::Minus,
230+
BinaryOperator::Eq => Operator::Eq,
231+
BinaryOperator::NotEq => Operator::NotEq,
232+
BinaryOperator::Gt => Operator::Gt,
233+
BinaryOperator::GtEq => Operator::GtEq,
234+
BinaryOperator::Lt => Operator::Lt,
235+
BinaryOperator::LtEq => Operator::LtEq,
230236
_ => {
231237
return not_impl_err!("Unsupported interval operator: {op:?}");
232238
}

datafusion/sql/tests/cases/plan_to_sql.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,34 @@ fn test_pretty_roundtrip() -> Result<()> {
549549

550550
Ok(())
551551
}
552+
553+
fn sql_round_trip(query: &str, expect: &str) {
554+
let statement = Parser::new(&GenericDialect {})
555+
.try_with_sql(query)
556+
.unwrap()
557+
.parse_statement()
558+
.unwrap();
559+
560+
let context = MockContextProvider::default();
561+
let sql_to_rel = SqlToRel::new(&context);
562+
let plan = sql_to_rel.sql_statement_to_plan(statement).unwrap();
563+
564+
let roundtrip_statement = plan_to_sql(&plan).unwrap();
565+
assert_eq!(roundtrip_statement.to_string(), expect);
566+
}
567+
568+
#[test]
569+
fn test_interval_lhs_eq() {
570+
sql_round_trip(
571+
"select interval '2 seconds' = interval '2 seconds'",
572+
"SELECT (INTERVAL '0 YEARS 0 MONS 0 DAYS 0 HOURS 0 MINS 2.000000000 SECS' = INTERVAL '0 YEARS 0 MONS 0 DAYS 0 HOURS 0 MINS 2.000000000 SECS')",
573+
);
574+
}
575+
576+
#[test]
577+
fn test_interval_lhs_lt() {
578+
sql_round_trip(
579+
"select interval '2 seconds' < interval '2 seconds'",
580+
"SELECT (INTERVAL '0 YEARS 0 MONS 0 DAYS 0 HOURS 0 MINS 2.000000000 SECS' < INTERVAL '0 YEARS 0 MONS 0 DAYS 0 HOURS 0 MINS 2.000000000 SECS')",
581+
);
582+
}

datafusion/sqllogictest/test_files/timestamps.slt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,6 +3109,68 @@ SELECT * FROM VALUES
31093109
2024-02-01T08:00:00Z
31103110
2023-12-31T23:00:00Z
31113111

3112+
# interval vs. duration comparison
3113+
query B
3114+
select (now() - now()) < interval '1 seconds';
3115+
----
3116+
true
3117+
3118+
query B
3119+
select (now() - now()) <= interval '1 seconds';
3120+
----
3121+
true
3122+
3123+
query B
3124+
select (now() - now()) = interval '0 seconds';
3125+
----
3126+
true
3127+
3128+
query B
3129+
select (now() - now()) != interval '1 seconds';
3130+
----
3131+
true
3132+
3133+
query B
3134+
select (now() - now()) > interval '-1 seconds';
3135+
----
3136+
true
3137+
3138+
query B
3139+
select (now() - now()) >= interval '-1 seconds';
3140+
----
3141+
true
3142+
3143+
query B
3144+
select arrow_cast(123, 'Duration(Nanosecond)') < interval '200 nanoseconds';
3145+
----
3146+
true
3147+
3148+
query B
3149+
select arrow_cast(123, 'Duration(Nanosecond)') < interval '100 nanoseconds';
3150+
----
3151+
false
3152+
3153+
query B
3154+
select arrow_cast(123, 'Duration(Nanosecond)') < interval '1 seconds';
3155+
----
3156+
true
3157+
3158+
query B
3159+
select interval '1 seconds' < arrow_cast(123, 'Duration(Nanosecond)')
3160+
----
3161+
false
3162+
3163+
# interval as LHS
3164+
query B
3165+
select interval '2 seconds' = interval '2 seconds';
3166+
----
3167+
true
3168+
3169+
query B
3170+
select interval '1 seconds' < interval '2 seconds';
3171+
----
3172+
true
3173+
31123174
statement ok
31133175
drop table t;
31143176

0 commit comments

Comments
 (0)