-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support binary mathematical operators work with NULL
literals
#2610
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -282,7 +282,7 @@ fn mathematics_numerical_coercion( | |
use arrow::datatypes::DataType::*; | ||
|
||
// error on any non-numeric type | ||
if !is_numeric(lhs_type) || !is_numeric(rhs_type) { | ||
if !both_numeric_or_null_and_numeric(lhs_type, rhs_type) { | ||
return None; | ||
}; | ||
|
||
|
@@ -412,6 +412,15 @@ pub fn is_numeric(dt: &DataType) -> bool { | |
} | ||
} | ||
|
||
/// Determine if at least of one of lhs and rhs is numeric, and the other must be NULL or numeric | ||
fn both_numeric_or_null_and_numeric(lhs_type: &DataType, rhs_type: &DataType) -> bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
match (lhs_type, rhs_type) { | ||
(_, DataType::Null) => is_numeric(lhs_type), | ||
(DataType::Null, _) => is_numeric(rhs_type), | ||
_ => is_numeric(lhs_type) && is_numeric(rhs_type), | ||
} | ||
} | ||
|
||
/// Coercion rules for dictionary values (aka the type of the dictionary itself) | ||
fn dictionary_value_coercion( | ||
lhs_type: &DataType, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -701,16 +701,58 @@ macro_rules! compute_bool_op { | |
/// LEFT is array, RIGHT is scalar value | ||
macro_rules! compute_op_scalar { | ||
($LEFT:expr, $RIGHT:expr, $OP:ident, $DT:ident) => {{ | ||
let ll = $LEFT | ||
.as_any() | ||
.downcast_ref::<$DT>() | ||
.expect("compute_op failed to downcast array"); | ||
// generate the scalar function name, such as lt_scalar, from the $OP parameter | ||
// (which could have a value of lt) and the suffix _scalar | ||
Ok(Arc::new(paste::expr! {[<$OP _scalar>]}( | ||
&ll, | ||
$RIGHT.try_into()?, | ||
)?)) | ||
match $RIGHT { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if you could use https://github.com/apache/arrow-datafusion/blob/master/datafusion/common/src/scalar.rs#L627 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice catch! |
||
ScalarValue::Int8(v) => compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT), | ||
ScalarValue::Int16(v) => compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT), | ||
ScalarValue::Int32(v) => compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT), | ||
ScalarValue::Int64(v) => compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT), | ||
ScalarValue::UInt8(v) => compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT), | ||
ScalarValue::UInt16(v) => { | ||
compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT) | ||
} | ||
ScalarValue::UInt32(v) => { | ||
compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT) | ||
} | ||
ScalarValue::UInt64(v) => { | ||
compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT) | ||
} | ||
ScalarValue::Float32(v) => { | ||
compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT) | ||
} | ||
ScalarValue::Float64(v) => { | ||
compute_array_op_scalar!($LEFT, $RIGHT, v, $OP, $DT) | ||
} | ||
_ => { | ||
let ll = $LEFT | ||
.as_any() | ||
.downcast_ref::<$DT>() | ||
.expect("compute_op failed to downcast array"); | ||
Ok(Arc::new(paste::expr! {[<$OP _scalar>]}( | ||
&ll, | ||
$RIGHT.try_into()?, | ||
)?)) | ||
} | ||
} | ||
}}; | ||
} | ||
|
||
/// Invoke a compute kernel on a data array and a scalar value | ||
/// return NULL array of LEFT's data type if RIGHT is NULL | ||
macro_rules! compute_array_op_scalar { | ||
($LEFT:expr, $RIGHT_SCALAR:expr, $RIGHT:expr, $OP:ident, $DT:ident) => {{ | ||
if let Some(_) = $RIGHT { | ||
let ll = $LEFT | ||
.as_any() | ||
.downcast_ref::<$DT>() | ||
.expect("compute_op failed to downcast array"); | ||
Ok(Arc::new(paste::expr! {[<$OP _scalar>]}( | ||
&ll, | ||
$RIGHT_SCALAR.try_into()?, | ||
)?)) | ||
} else { | ||
// when the $RIGHT is a NULL, generate a NULL array of $LEFT's data type | ||
Ok(Arc::new(new_null_array($LEFT.data_type(), $LEFT.len()))) | ||
} | ||
}}; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.