Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions datafusion/common/src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,21 @@ macro_rules! primitive_right {
"Can not divide an uninitialized value to a non-floating point value",
)))
};
($TERM:expr, &, $SCALAR:ident) => {
Ok(ScalarValue::$SCALAR(Some($TERM)))
};
($TERM:expr, |, $SCALAR:ident) => {
Ok(ScalarValue::$SCALAR(Some($TERM)))
};
($TERM:expr, ^, $SCALAR:ident) => {
Ok(ScalarValue::$SCALAR(Some($TERM)))
};
($TERM:expr, &&, $SCALAR:ident) => {
Ok(ScalarValue::$SCALAR(Some($TERM)))
};
($TERM:expr, ||, $SCALAR:ident) => {
Ok(ScalarValue::$SCALAR(Some($TERM)))
};
}

macro_rules! unsigned_subtraction_error {
Expand Down Expand Up @@ -755,6 +770,74 @@ macro_rules! impl_op {
_ => impl_op_arithmetic!($LHS, $RHS, -)
}
};
($LHS:expr, $RHS:expr, &) => {
impl_bit_op_arithmetic!($LHS, $RHS, &)
};
($LHS:expr, $RHS:expr, |) => {
impl_bit_op_arithmetic!($LHS, $RHS, |)
};
($LHS:expr, $RHS:expr, ^) => {
impl_bit_op_arithmetic!($LHS, $RHS, ^)
};
($LHS:expr, $RHS:expr, &&) => {
impl_bool_op_arithmetic!($LHS, $RHS, &&)
};
($LHS:expr, $RHS:expr, ||) => {
impl_bool_op_arithmetic!($LHS, $RHS, ||)
};
}

macro_rules! impl_bit_op_arithmetic {
($LHS:expr, $RHS:expr, $OPERATION:tt) => {
match ($LHS, $RHS) {
(ScalarValue::UInt64(lhs), ScalarValue::UInt64(rhs)) => {
primitive_op!(lhs, rhs, UInt64, $OPERATION)
}
(ScalarValue::Int64(lhs), ScalarValue::Int64(rhs)) => {
primitive_op!(lhs, rhs, Int64, $OPERATION)
}
(ScalarValue::UInt32(lhs), ScalarValue::UInt32(rhs)) => {
primitive_op!(lhs, rhs, UInt32, $OPERATION)
}
(ScalarValue::Int32(lhs), ScalarValue::Int32(rhs)) => {
primitive_op!(lhs, rhs, Int32, $OPERATION)
}
(ScalarValue::UInt16(lhs), ScalarValue::UInt16(rhs)) => {
primitive_op!(lhs, rhs, UInt16, $OPERATION)
}
(ScalarValue::Int16(lhs), ScalarValue::Int16(rhs)) => {
primitive_op!(lhs, rhs, Int16, $OPERATION)
}
(ScalarValue::UInt8(lhs), ScalarValue::UInt8(rhs)) => {
primitive_op!(lhs, rhs, UInt8, $OPERATION)
}
(ScalarValue::Int8(lhs), ScalarValue::Int8(rhs)) => {
primitive_op!(lhs, rhs, Int8, $OPERATION)
}
_ => Err(DataFusionError::Internal(format!(
"Operator {} is not implemented for types {:?} and {:?}",
stringify!($OPERATION),
$LHS,
$RHS
))),
}
};
}

macro_rules! impl_bool_op_arithmetic {
($LHS:expr, $RHS:expr, $OPERATION:tt) => {
match ($LHS, $RHS) {
(ScalarValue::Boolean(lhs), ScalarValue::Boolean(rhs)) => {
primitive_op!(lhs, rhs, Boolean, $OPERATION)
}
_ => Err(DataFusionError::Internal(format!(
"Operator {} is not implemented for types {:?} and {:?}",
stringify!($OPERATION),
$LHS,
$RHS
))),
}
};
}

macro_rules! impl_op_arithmetic {
Expand Down Expand Up @@ -1951,6 +2034,31 @@ impl ScalarValue {
impl_checked_op!(self, rhs, checked_sub, -)
}

pub fn and<T: Borrow<ScalarValue>>(&self, other: T) -> Result<ScalarValue> {
let rhs = other.borrow();
impl_op!(self, rhs, &&)
}

pub fn or<T: Borrow<ScalarValue>>(&self, other: T) -> Result<ScalarValue> {
let rhs = other.borrow();
impl_op!(self, rhs, ||)
}

pub fn bitand<T: Borrow<ScalarValue>>(&self, other: T) -> Result<ScalarValue> {
let rhs = other.borrow();
impl_op!(self, rhs, &)
}

pub fn bitor<T: Borrow<ScalarValue>>(&self, other: T) -> Result<ScalarValue> {
let rhs = other.borrow();
impl_op!(self, rhs, |)
}

pub fn bitxor<T: Borrow<ScalarValue>>(&self, other: T) -> Result<ScalarValue> {
let rhs = other.borrow();
impl_op!(self, rhs, ^)
}

pub fn is_unsigned(&self) -> bool {
matches!(
self,
Expand Down
96 changes: 96 additions & 0 deletions datafusion/core/tests/sqllogictests/test_files/aggregate.slt
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ SELECT avg(c12) FROM aggregate_test_100
----
0.508972509913

# csv_query_bit_and
query IIIII
SELECT bit_and(c5), bit_and(c6), bit_and(c7), bit_and(c8), bit_and(c9) FROM aggregate_test_100
----
0 0 0 0 0

# csv_query_bit_or
query IIIII
SELECT bit_or(c5), bit_or(c6), bit_or(c7), bit_or(c8), bit_or(c9) FROM aggregate_test_100
----
-1 -1 255 65535 4294967295

# csv_query_bit_xor
query IIIII
SELECT bit_xor(c5), bit_xor(c6), bit_xor(c7), bit_xor(c8), bit_xor(c9) FROM aggregate_test_100
----
1632751011 5960911605712039654 148 54789 169634700

# csv_query_covariance_1
query R
SELECT covar_pop(c2, c12) FROM aggregate_test_100
Expand Down Expand Up @@ -1355,6 +1373,27 @@ SELECT avg(column1), column2 from the_nulls group by column2 order by column2;
NULL 1
NULL 2

# bit_and should be null
query II
SELECT bit_and(column1), column2 from the_nulls group by column2 order by column2;
----
NULL 1
NULL 2

# bit_or should be null
query II
SELECT bit_or(column1), column2 from the_nulls group by column2 order by column2;
----
NULL 1
NULL 2

# bit_xor should be null
query II
SELECT bit_xor(column1), column2 from the_nulls group by column2 order by column2;
----
NULL 1
NULL 2

# min should be null
query II
SELECT min(column1), column2 from the_nulls group by column2 order by column2;
Expand Down Expand Up @@ -1390,6 +1429,63 @@ as values
('2021-01-01T05:11:10.432', 'Row 3');


statement ok
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given postgres also runs these queries what do you think about also adding them into a pg_compat test in https://github.com/apache/arrow-datafusion/tree/main/datafusion/core/tests/sqllogictests/test_files/pg_compat?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a nice idea for bitwise aggregate functions.

create table bit_aggregate_functions (
c1 SMALLINT NOT NULL,
c2 SMALLINT NOT NULL,
c3 SMALLINT,
)
as values
(5, 10, 11),
(33, 11, null),
(9, 12, null);

# query_bit_and
query III
SELECT bit_and(c1), bit_and(c2), bit_and(c3) FROM bit_aggregate_functions
----
1 8 11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double checked this is consistent with postgres 👍


# query_bit_or
query III
SELECT bit_or(c1), bit_or(c2), bit_or(c3) FROM bit_aggregate_functions
----
45 15 11

# query_bit_xor
query III
SELECT bit_xor(c1), bit_xor(c2), bit_xor(c3) FROM bit_aggregate_functions
----
45 13 11

statement ok
create table bool_aggregate_functions (
c1 boolean not null,
c2 boolean not null,
c3 boolean not null,
c4 boolean not null,
c5 boolean,
c6 boolean,
c7 boolean,
c8 boolean,
)
as values
(true, true, false, false, true, true, null, null),
(true, false, true, false, false, null, false, null),
(true, true, false, false, null, true, false, null);

# query_bool_and
query BBBBBBBB
SELECT bool_and(c1), bool_and(c2), bool_and(c3), bool_and(c4), bool_and(c5), bool_and(c6), bool_and(c7), bool_and(c8) FROM bool_aggregate_functions
----
true false false false false true false NULL

# query_bool_or
query BBBBBBBB
SELECT bool_or(c1), bool_or(c2), bool_or(c3), bool_or(c4), bool_or(c5), bool_or(c6), bool_or(c7), bool_or(c8) FROM bool_aggregate_functions
----
true true true false true true false NULL

statement ok
create table t as
select
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,36 +325,42 @@ AS tbl(int_col, float_col, negative_col, summation);
10 20 -30 4


query IIRIII
query IIRIIIIII
SELECT
count(*) AS count_all,
count(c3) AS count_c3,
avg(c3) AS avg,
sum(c3) AS sum,
max(c3) AS max,
min(c3) AS min
min(c3) AS min,
bit_and(c3) as bit_and,
bit_or(c3) as bit_or,
bit_xor(c3) as bit_xor
FROM aggregate_test_100_by_sql;
----
100 100 7.81 781 125 -117
100 100 7.81 781 125 -117 0 -1 -61


query IIRIII
query IIRIIIIII
select
c2,
sum(c3) sum_c3,
avg(c3) avg_c3,
max(c3) max_c3,
min(c3) min_c3,
count(c3) count_c3
count(c3) count_c3,
bit_and(c3) bit_and_c3,
bit_or(c3) bit_or_c3,
bit_xor(c3) bit_xor_c3
from aggregate_test_100_by_sql
group by c2
order by c2;
----
1 367 16.681818181818 125 -99 22
2 184 8.363636363636 122 -117 22
3 395 20.789473684211 123 -101 19
4 29 1.260869565217 123 -117 23
5 -194 -13.857142857143 118 -101 14
1 367 16.681818181818 125 -99 22 0 -1 -47
2 184 8.363636363636 122 -117 22 0 -1 -2
3 395 20.789473684211 123 -101 19 0 -1 101
4 29 1.260869565217 123 -117 23 0 -1 15
5 -194 -13.857142857143 118 -101 14 0 -1 -122


query I
Expand Down
Loading