diff --git a/datafusion/core/tests/sqllogictests/test_files/binary.slt b/datafusion/core/tests/sqllogictests/test_files/binary.slt index ca55ff56cb1c..54499e29787b 100644 --- a/datafusion/core/tests/sqllogictests/test_files/binary.slt +++ b/datafusion/core/tests/sqllogictests/test_files/binary.slt @@ -45,6 +45,23 @@ FF01 ff01 Utf8 Binary ABC 0abc Utf8 Binary 000 0000 Utf8 Binary +# comparisons +query ?BBBB +SELECT + column2, + -- binary compare with string + column2 = 'ABC', + column2 <> 'ABC', + -- binary compared with binary + column2 = X'ABC', + column2 <> X'ABC' +FROM t; +---- +ff01 false true false true +0abc false true true false +0000 false true false true + + # predicates query T? SELECT column1, column2 @@ -127,3 +144,9 @@ SELECT column1, column1 = arrow_cast(X'0102', 'FixedSizeBinary(2)') FROM t # Comparison to different sized Binary query error DataFusion error: Error during planning: Cannot infer common argument type for comparison operation FixedSizeBinary\(3\) = Binary SELECT column1, column1 = X'0102' FROM t + +statement ok +drop table t_source + +statement ok +drop table t diff --git a/datafusion/expr/src/type_coercion/binary.rs b/datafusion/expr/src/type_coercion/binary.rs index b6392e2a6be2..492977fd8b72 100644 --- a/datafusion/expr/src/type_coercion/binary.rs +++ b/datafusion/expr/src/type_coercion/binary.rs @@ -315,6 +315,7 @@ pub fn comparison_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option Option } } +/// Coercion rules for Binaries: the type that both lhs and rhs can be +/// casted to for the purpose of a computation +fn binary_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option { + use arrow::datatypes::DataType::*; + match (lhs_type, rhs_type) { + (Binary | Utf8, Binary) | (Binary, Utf8) => Some(Binary), + (LargeBinary | Binary | Utf8 | LargeUtf8, LargeBinary) + | (LargeBinary, Binary | Utf8 | LargeUtf8) => Some(LargeBinary), + _ => None, + } +} + /// coercion rules for like operations. /// This is a union of string coercion rules and dictionary coercion rules pub fn like_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option { @@ -1036,10 +1049,13 @@ mod tests { let rhs_type = Dictionary(Box::new(Int8), Box::new(Int16)); assert_eq!(dictionary_coercion(&lhs_type, &rhs_type, true), Some(Utf8)); - // Can not coerce values of Binary to int, cannot support this + // Since we can coerce values of Utf8 to Binary can support this let lhs_type = Dictionary(Box::new(Int8), Box::new(Utf8)); let rhs_type = Dictionary(Box::new(Int8), Box::new(Binary)); - assert_eq!(dictionary_coercion(&lhs_type, &rhs_type, true), None); + assert_eq!( + dictionary_coercion(&lhs_type, &rhs_type, true), + Some(Binary) + ); let lhs_type = Dictionary(Box::new(Int8), Box::new(Utf8)); let rhs_type = Utf8; @@ -1440,6 +1456,70 @@ mod tests { DataType::Decimal128(15, 3) ); + // Binary + test_coercion_binary_rule!( + DataType::Binary, + DataType::Binary, + Operator::Eq, + DataType::Binary + ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::Binary, + Operator::Eq, + DataType::Binary + ); + test_coercion_binary_rule!( + DataType::Binary, + DataType::Utf8, + Operator::Eq, + DataType::Binary + ); + + // LargeBinary + test_coercion_binary_rule!( + DataType::LargeBinary, + DataType::LargeBinary, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::Binary, + DataType::LargeBinary, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::LargeBinary, + DataType::Binary, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::Utf8, + DataType::LargeBinary, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::LargeBinary, + DataType::Utf8, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::LargeUtf8, + DataType::LargeBinary, + Operator::Eq, + DataType::LargeBinary + ); + test_coercion_binary_rule!( + DataType::LargeBinary, + DataType::LargeUtf8, + Operator::Eq, + DataType::LargeBinary + ); + // TODO add other data type Ok(()) }