You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by al...@apache.org on 2022/12/19 19:31:12 UTC

[arrow-datafusion] branch master updated: More descriptive error for plus/minus between timestamps/dates (#4662)

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

alamb 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 975ff15b2 More descriptive error for plus/minus between timestamps/dates (#4662)
975ff15b2 is described below

commit 975ff15b25bdfe198db8c5b440f08cca45b2f482
Author: Jeffrey <22...@users.noreply.github.com>
AuthorDate: Tue Dec 20 06:31:06 2022 +1100

    More descriptive error for plus/minus between timestamps/dates (#4662)
---
 datafusion/expr/src/type_coercion/binary.rs | 38 +++++++++++++++++++++++++----
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/datafusion/expr/src/type_coercion/binary.rs b/datafusion/expr/src/type_coercion/binary.rs
index db4b242b0..8105b6d24 100644
--- a/datafusion/expr/src/type_coercion/binary.rs
+++ b/datafusion/expr/src/type_coercion/binary.rs
@@ -17,7 +17,7 @@
 
 //! Coercion rules for matching argument types for binary operators
 
-use crate::type_coercion::is_numeric;
+use crate::type_coercion::{is_date, is_numeric, is_timestamp};
 use crate::Operator;
 use arrow::compute::can_cast_types;
 use arrow::datatypes::{
@@ -121,14 +121,22 @@ pub fn coerce_types(
         Operator::Like | Operator::NotLike | Operator::ILike | Operator::NotILike => {
             like_coercion(lhs_type, rhs_type)
         }
-        // date +/- interval returns date
         Operator::Plus | Operator::Minus
-            if (*lhs_type == DataType::Date32
-                || *lhs_type == DataType::Date64
-                || matches!(lhs_type, DataType::Timestamp(_, _))) =>
+            if is_date(lhs_type) || is_timestamp(lhs_type) =>
         {
             match rhs_type {
+                // timestamp/date +/- interval returns timestamp/date
                 DataType::Interval(_) => Some(lhs_type.clone()),
+                // providing more helpful error message
+                DataType::Date32 | DataType::Date64 | DataType::Timestamp(_, _) => {
+                    return Err(DataFusionError::Plan(
+                        format!(
+                            "'{:?} {} {:?}' is an unsupported operation. \
+                                addition/subtraction on dates/timestamps only supported with interval types",
+                            lhs_type, op, rhs_type
+                        ),
+                    ));
+                }
                 _ => None,
             }
         }
@@ -672,6 +680,7 @@ mod tests {
     use super::*;
     use crate::Operator;
     use arrow::datatypes::DataType;
+    use datafusion_common::assert_contains;
     use datafusion_common::DataFusionError;
     use datafusion_common::Result;
 
@@ -848,6 +857,25 @@ mod tests {
         }};
     }
 
+    #[test]
+    fn test_date_timestamp_arithmetic_error() -> Result<()> {
+        let err = coerce_types(
+            &DataType::Timestamp(TimeUnit::Nanosecond, None),
+            &Operator::Minus,
+            &DataType::Timestamp(TimeUnit::Nanosecond, None),
+        )
+        .unwrap_err()
+        .to_string();
+        assert_contains!(&err, "'Timestamp(Nanosecond, None) - Timestamp(Nanosecond, None)' is an unsupported operation. addition/subtraction on dates/timestamps only supported with interval types");
+
+        let err = coerce_types(&DataType::Date32, &Operator::Plus, &DataType::Date64)
+            .unwrap_err()
+            .to_string();
+        assert_contains!(&err, "'Date32 + Date64' is an unsupported operation. addition/subtraction on dates/timestamps only supported with interval types");
+
+        Ok(())
+    }
+
     #[test]
     fn test_type_coercion() -> Result<()> {
         test_coercion_binary_rule!(