This is an automated email from the ASF dual-hosted git repository.
dheres pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new e7850d1e1c fix: disallow interval - timestamp (#7086)
e7850d1e1c is described below
commit e7850d1e1c6a8d4d6a82448b67aedbc6455b8cd9
Author: jakevin <[email protected]>
AuthorDate: Wed Jul 26 00:50:26 2023 +0800
fix: disallow interval - timestamp (#7086)
---
.../core/tests/sqllogictests/test_files/insert.slt | 2 +-
.../tests/sqllogictests/test_files/interval.slt | 32 ++++------------------
.../sqllogictests/test_files/type_coercion.slt | 8 ++----
datafusion/expr/src/type_coercion/binary.rs | 19 +++++++------
4 files changed, 20 insertions(+), 41 deletions(-)
diff --git a/datafusion/core/tests/sqllogictests/test_files/insert.slt
b/datafusion/core/tests/sqllogictests/test_files/insert.slt
index faa519834c..9f4122ac5b 100644
--- a/datafusion/core/tests/sqllogictests/test_files/insert.slt
+++ b/datafusion/core/tests/sqllogictests/test_files/insert.slt
@@ -299,4 +299,4 @@ select * from table_without_values;
2 NULL
statement ok
-drop table table_without_values;
\ No newline at end of file
+drop table table_without_values;
diff --git a/datafusion/core/tests/sqllogictests/test_files/interval.slt
b/datafusion/core/tests/sqllogictests/test_files/interval.slt
index 1016cb155e..043f63958d 100644
--- a/datafusion/core/tests/sqllogictests/test_files/interval.slt
+++ b/datafusion/core/tests/sqllogictests/test_files/interval.slt
@@ -430,15 +430,11 @@ select '1 month'::interval +
'1980-01-01T12:00:00'::timestamp;
----
1980-02-01T12:00:00
-query D
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Date32 to valid types
select '1 month'::interval - '1980-01-01'::date;
-----
-1979-12-01
-query P
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Timestamp\(Nanosecond, None\) to valid
types
select '1 month'::interval - '1980-01-01T12:00:00'::timestamp;
-----
-1979-12-01T12:00:00
# interval (array) + date / timestamp (array)
query D
@@ -456,19 +452,11 @@ select i + ts from t;
2000-02-01T00:01:00
# expected error interval (array) - date / timestamp (array)
-query D
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Date32 to valid types
select i - d from t;
-----
-1979-12-01
-1990-09-30
-1980-01-02
-query P
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Timestamp\(Nanosecond, None\) to valid
types
select i - ts from t;
-----
-1999-12-01T00:00:00
-1999-12-31T12:11:10
-2000-01-31T23:59:00
# interval (scalar) + date / timestamp (array)
@@ -487,19 +475,11 @@ select '1 month'::interval + ts from t;
2000-03-01T00:00:00
# expected error interval (scalar) - date / timestamp (array)
-query D
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Date32 to valid types
select '1 month'::interval - d from t;
-----
-1979-12-01
-1990-09-01
-1979-12-02
-query P
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Timestamp\(Nanosecond, None\) to valid
types
select '1 month'::interval - ts from t;
-----
-1999-12-01T00:00:00
-1999-12-01T12:11:10
-2000-01-01T00:00:00
# interval + date
query D
diff --git a/datafusion/core/tests/sqllogictests/test_files/type_coercion.slt
b/datafusion/core/tests/sqllogictests/test_files/type_coercion.slt
index 8b329df0c1..aa1e6826ec 100644
--- a/datafusion/core/tests/sqllogictests/test_files/type_coercion.slt
+++ b/datafusion/core/tests/sqllogictests/test_files/type_coercion.slt
@@ -43,13 +43,9 @@ SELECT '2023-05-01 12:30:00'::timestamp - interval '1 month';
2023-04-01T12:30:00
# interval - date
-query D
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Date32 to valid types
select interval '1 month' - '2023-05-01'::date;
-----
-2023-04-01
# interval - timestamp
-query P
+query error DataFusion error: Error during planning: Cannot coerce arithmetic
expression Interval\(MonthDayNano\) \- Timestamp\(Nanosecond, None\) to valid
types
SELECT interval '1 month' - '2023-05-01 12:30:00'::timestamp;
-----
-2023-04-01T12:30:00
diff --git a/datafusion/expr/src/type_coercion/binary.rs
b/datafusion/expr/src/type_coercion/binary.rs
index b6392e2a6b..56a5664638 100644
--- a/datafusion/expr/src/type_coercion/binary.rs
+++ b/datafusion/expr/src/type_coercion/binary.rs
@@ -120,7 +120,7 @@ fn signature(lhs: &DataType, op: &Operator, rhs: &DataType)
-> Result<Signature>
Operator::Divide|
Operator::Modulo => {
// TODO: this logic would be easier to follow if the functions
were inlined
- if let Some(ret) = mathematics_temporal_result_type(lhs, rhs) {
+ if let Some(ret) = mathematics_temporal_result_type(lhs, rhs, op) {
// Temporal arithmetic, e.g. Date32 + Interval
Ok(Signature{
lhs: lhs.clone(),
@@ -130,7 +130,7 @@ fn signature(lhs: &DataType, op: &Operator, rhs: &DataType)
-> Result<Signature>
} else if let Some(coerced) = temporal_coercion(lhs, rhs) {
// Temporal arithmetic by first coercing to a common time
representation
// e.g. Date32 - Timestamp
- let ret = mathematics_temporal_result_type(&coerced,
&coerced).ok_or_else(|| {
+ let ret = mathematics_temporal_result_type(&coerced, &coerced,
op).ok_or_else(|| {
DataFusionError::Plan(format!(
"Cannot get result type for temporal operation
{coerced} {op} {coerced}"
))
@@ -169,6 +169,7 @@ fn signature(lhs: &DataType, op: &Operator, rhs: &DataType)
-> Result<Signature>
fn mathematics_temporal_result_type(
lhs_type: &DataType,
rhs_type: &DataType,
+ op: &Operator,
) -> Option<DataType> {
use arrow::datatypes::DataType::*;
use arrow::datatypes::IntervalUnit::*;
@@ -176,12 +177,14 @@ fn mathematics_temporal_result_type(
match (lhs_type, rhs_type) {
// datetime +/- interval
- (Interval(_), Timestamp(_, _)) => Some(rhs_type.clone()),
- (Timestamp(_, _), Interval(_)) => Some(lhs_type.clone()),
- (Interval(_), Date32) => Some(rhs_type.clone()),
- (Date32, Interval(_)) => Some(lhs_type.clone()),
- (Interval(_), Date64) => Some(rhs_type.clone()),
- (Date64, Interval(_)) => Some(lhs_type.clone()),
+ (Timestamp(_, _) | Date32 | Date64, Interval(_)) =>
Some(lhs_type.clone()),
+ (Interval(_), Timestamp(_, _) | Date32 | Date64) => {
+ if matches!(op, Operator::Plus) {
+ Some(rhs_type.clone())
+ } else {
+ None
+ }
+ }
// interval +/-
(Interval(l), Interval(h)) if l == h => Some(lhs_type.clone()),
(Interval(_), Interval(_)) => Some(Interval(MonthDayNano)),