Skip to content

Commit

Permalink
Like, NotLike expressions work with literal NULL (apache#2627)
Browse files Browse the repository at this point in the history
* like / not like work with NULL

* add more ut
  • Loading branch information
WinkerDu authored and ovr committed Aug 15, 2022
1 parent 5be64ab commit 90615fb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 5 deletions.
30 changes: 30 additions & 0 deletions datafusion/core/tests/sql/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,36 @@ async fn nested_subquery() -> Result<()> {
Ok(())
}

#[tokio::test]
async fn like_nlike_with_null_lt() {
let ctx = SessionContext::new();
let sql = "SELECT column1 like NULL as col_null, NULL like column1 as null_col from (values('a'), ('b'), (NULL)) as t";
let actual = execute_to_batches(&ctx, sql).await;
let expected = vec![
"+----------+----------+",
"| col_null | null_col |",
"+----------+----------+",
"| | |",
"| | |",
"| | |",
"+----------+----------+",
];
assert_batches_eq!(expected, &actual);

let sql = "SELECT column1 not like NULL as col_null, NULL not like column1 as null_col from (values('a'), ('b'), (NULL)) as t";
let actual = execute_to_batches(&ctx, sql).await;
let expected = vec![
"+----------+----------+",
"| col_null | null_col |",
"+----------+----------+",
"| | |",
"| | |",
"| | |",
"+----------+----------+",
];
assert_batches_eq!(expected, &actual);
}

#[tokio::test]
async fn comparisons_with_null_lt() {
let ctx = SessionContext::new();
Expand Down
1 change: 1 addition & 0 deletions datafusion/physical-expr/src/coercion_rule/binary_rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ fn string_boolean_equality_coercion(
fn like_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option<DataType> {
string_coercion(lhs_type, rhs_type)
.or_else(|| dictionary_coercion(lhs_type, rhs_type))
.or_else(|| null_coercion(lhs_type, rhs_type))
}

/// Coercion rules for Temporal columns: the type that both lhs and rhs can be
Expand Down
12 changes: 7 additions & 5 deletions datafusion/physical-expr/src/expressions/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ macro_rules! compute_utf8_op {

/// Invoke a compute kernel on a data array and a scalar value
macro_rules! compute_utf8_op_scalar {
($LEFT:expr, $RIGHT:expr, $OP:ident, $DT:ident) => {{
($LEFT:expr, $RIGHT:expr, $OP:ident, $DT:ident, $OP_TYPE:expr) => {{
let ll = $LEFT
.as_any()
.downcast_ref::<$DT>()
Expand All @@ -831,6 +831,8 @@ macro_rules! compute_utf8_op_scalar {
&ll,
&string_value,
)?))
} else if $RIGHT.is_null() {
Ok(Arc::new(new_null_array($OP_TYPE, $LEFT.len())))
} else {
Err(DataFusionError::Internal(format!(
"compute_utf8_op_scalar for '{}' failed to cast literal value {}",
Expand Down Expand Up @@ -960,9 +962,9 @@ macro_rules! compute_op {
}

macro_rules! binary_string_array_op_scalar {
($LEFT:expr, $RIGHT:expr, $OP:ident) => {{
($LEFT:expr, $RIGHT:expr, $OP:ident, $OP_TYPE:expr) => {{
let result: Result<Arc<dyn Array>> = match $LEFT.data_type() {
DataType::Utf8 => compute_utf8_op_scalar!($LEFT, $RIGHT, $OP, StringArray),
DataType::Utf8 => compute_utf8_op_scalar!($LEFT, $RIGHT, $OP, StringArray, $OP_TYPE),
other => Err(DataFusionError::Internal(format!(
"Data type {:?} not supported for scalar operation '{}' on string array",
other, stringify!($OP)
Expand Down Expand Up @@ -1364,10 +1366,10 @@ impl BinaryExpr {
binary_array_op_dyn_scalar!(array, scalar.clone(), neq, bool_type)
}
Operator::Like => {
binary_string_array_op_scalar!(array, scalar.clone(), like)
binary_string_array_op_scalar!(array, scalar.clone(), like, bool_type)
}
Operator::NotLike => {
binary_string_array_op_scalar!(array, scalar.clone(), nlike)
binary_string_array_op_scalar!(array, scalar.clone(), nlike, bool_type)
}
Operator::ILike => {
binary_string_array_op_scalar!(array, scalar.clone(), ilike)
Expand Down

0 comments on commit 90615fb

Please sign in to comment.