You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by dh...@apache.org on 2022/04/15 06:51:40 UTC

[arrow-datafusion] branch master updated: Add type coercion rule for date + interval (#2235)

This is an automated email from the ASF dual-hosted git repository.

dheres pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git


The following commit(s) were added to refs/heads/master by this push:
     new 3d2e7b0bf Add type coercion rule for date + interval (#2235)
3d2e7b0bf is described below

commit 3d2e7b0bfb27fe5c9009382b3840ba88595dfbb4
Author: Andy Grove <ag...@apache.org>
AuthorDate: Fri Apr 15 00:51:36 2022 -0600

    Add type coercion rule for date + interval (#2235)
    
    Signed-off-by: Andy Grove <ag...@apache.org>
---
 datafusion/core/src/sql/planner.rs                 | 25 ++++++++++++++++++++++
 .../physical-expr/src/coercion_rule/binary_rule.rs |  9 ++++++++
 2 files changed, 34 insertions(+)

diff --git a/datafusion/core/src/sql/planner.rs b/datafusion/core/src/sql/planner.rs
index 12bae6ba0..536682cf0 100644
--- a/datafusion/core/src/sql/planner.rs
+++ b/datafusion/core/src/sql/planner.rs
@@ -4033,6 +4033,10 @@ mod tests {
             name: TableReference,
         ) -> Option<Arc<dyn TableProvider>> {
             let schema = match name.table() {
+                "test" => Some(Schema::new(vec![
+                    Field::new("t_date32", DataType::Date32, false),
+                    Field::new("t_date64", DataType::Date64, false),
+                ])),
                 "person" => Some(Schema::new(vec![
                     Field::new("id", DataType::UInt32, false),
                     Field::new("first_name", DataType::Utf8, false),
@@ -4158,4 +4162,25 @@ mod tests {
         let result = logical_plan(sql).err().unwrap();
         assert_eq!(expected, format!("{}", result));
     }
+
+    #[test]
+    fn date_plus_interval_in_projection() {
+        let sql = "select t_date32 + interval '5 days' FROM test";
+        let expected = "Projection: #test.t_date32 + IntervalDayTime(\"21474836480\")\
+                            \n  TableScan: test projection=None";
+        quick_test(sql, expected);
+    }
+
+    #[test]
+    fn date_plus_interval_in_filter() {
+        let sql = "select t_date64 FROM test \
+                    WHERE t_date64 \
+                    BETWEEN cast('1999-12-31' as date) \
+                        AND cast('1999-12-31' as date) + interval '30 days'";
+        let expected =
+            "Projection: #test.t_date64\
+            \n  Filter: #test.t_date64 BETWEEN CAST(Utf8(\"1999-12-31\") AS Date32) AND CAST(Utf8(\"1999-12-31\") AS Date32) + IntervalDayTime(\"128849018880\")\
+            \n    TableScan: test projection=None";
+        quick_test(sql, expected);
+    }
 }
diff --git a/datafusion/physical-expr/src/coercion_rule/binary_rule.rs b/datafusion/physical-expr/src/coercion_rule/binary_rule.rs
index 263523938..7c61c34fc 100644
--- a/datafusion/physical-expr/src/coercion_rule/binary_rule.rs
+++ b/datafusion/physical-expr/src/coercion_rule/binary_rule.rs
@@ -48,6 +48,15 @@ pub(crate) fn coerce_types(
         }
         // "like" operators operate on strings and always return a boolean
         Operator::Like | Operator::NotLike => like_coercion(lhs_type, rhs_type),
+        // date +/- interval returns date
+        Operator::Plus | Operator::Minus
+            if (*lhs_type == DataType::Date32 || *lhs_type == DataType::Date64) =>
+        {
+            match rhs_type {
+                DataType::Interval(_) => Some(lhs_type.clone()),
+                _ => None,
+            }
+        }
         // for math expressions, the final value of the coercion is also the return type
         // because coercion favours higher information types
         Operator::Plus