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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions