Skip to content

Allow comparison netween booleans and integers #16797

@osipovartem

Description

@osipovartem
select true::boolean = 0

Returns cannot infer common argument type for comparison operation Boolean = Int64

Arrow allows casting between boolean and integer types
https://github.com/apache/arrow-rs/blob/main/arrow-cast/src/cast/mod.rs#L583-L595

pub fn can_cast_types(from_type: &DataType, to_type: &DataType) -> bool {
...
        (_, Boolean) => {
            DataType::is_integer(from_type)
                || DataType::is_floating(from_type)
                || from_type == &Utf8View
                || from_type == &Utf8
                || from_type == &LargeUtf8
        }
        (Boolean, _) => {
            DataType::is_integer(to_type)
                || DataType::is_floating(to_type)
                || to_type == &Utf8View
                || to_type == &Utf8
                || to_type == &LargeUtf8
        }

But we don't support this by comparison_coercion

    fn signature(&'a self) -> Result<Signature> {
        use arrow::datatypes::DataType::*;
        use Operator::*;
        let result = match self.op {
        Eq |
        NotEq |
        Lt |
        LtEq |
        Gt |
        GtEq |
        IsDistinctFrom |
        IsNotDistinctFrom => {
            comparison_coercion(self.lhs, self.rhs).map(Signature::comparison).ok_or_else(|| {
                plan_datafusion_err!(
                    "Cannot infer common argument type for comparison operation {} {} {}",
                    self.lhs,
                    self.op,
                    self.rhs
                )
            })
        }

Describe the solution you'd like

Extend comparison_coercion
with

/// Coercion rules for boolean types: If at least one argument is
/// a boolean type and both arguments can be coerced into a boolean type, coerce
/// to boolean type.
fn boolean_coercion(lhs_type: &DataType, rhs_type: &DataType) -> Option<DataType> {
    use arrow::datatypes::DataType::*;
    match (lhs_type, rhs_type) {
        (Boolean, Int8 | Int16 | Int32 | Int64 | UInt8 | UInt16 | UInt32 | UInt64)
        | (Int8 | Int16 | Int32 | Int64 | UInt8 | UInt16 | UInt32 | UInt64, Boolean) => {
            Some(Boolean)
        }
        _ => None,
    }
}

Describe alternatives you've considered

No response

Additional context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions