@@ -19,13 +19,13 @@ use std::any::Any;
1919use std:: sync:: Arc ;
2020
2121use arrow:: array:: {
22- Array , ArrayRef , BinaryArray , BinaryViewArray , FixedSizeBinaryArray , Int64Array ,
23- LargeBinaryArray ,
22+ as_dictionary_array , Array , ArrayRef , BinaryArray , BinaryViewArray ,
23+ FixedSizeBinaryArray , Int64Array , LargeBinaryArray ,
2424} ;
25- use arrow:: datatypes:: DataType ;
2625use arrow:: datatypes:: DataType :: {
27- Binary , BinaryView , FixedSizeBinary , Int64 , LargeBinary ,
26+ Binary , BinaryView , Dictionary , FixedSizeBinary , LargeBinary ,
2827} ;
28+ use arrow:: datatypes:: { DataType , Int16Type , Int32Type , Int64Type , Int8Type } ;
2929use datafusion_common:: utils:: take_function_args;
3030use datafusion_common:: { internal_err, Result } ;
3131use datafusion_expr:: {
@@ -71,7 +71,7 @@ impl ScalarUDFImpl for BitmapCount {
7171 }
7272
7373 fn return_type ( & self , _arg_types : & [ DataType ] ) -> Result < DataType > {
74- Ok ( Int64 )
74+ Ok ( DataType :: Int64 )
7575 }
7676
7777 fn invoke_with_args ( & self , args : ScalarFunctionArgs ) -> Result < ColumnarValue > {
@@ -90,6 +90,17 @@ macro_rules! downcast_and_count_ones {
9090 } } ;
9191}
9292
93+ macro_rules! downcast_dict_and_count_ones {
94+ ( $input_dict: expr, $key_array_type: ident) => { {
95+ let dict_array = as_dictionary_array:: <$key_array_type>( $input_dict) ;
96+ let array = dict_array. downcast_dict:: <BinaryArray >( ) . unwrap( ) ;
97+ Ok ( array
98+ . into_iter( )
99+ . map( binary_count_ones)
100+ . collect:: <Int64Array >( ) )
101+ } } ;
102+ }
103+
93104pub fn bitmap_count_inner ( arg : & [ ArrayRef ] ) -> Result < ArrayRef > {
94105 let [ input_array] = take_function_args ( "bitmap_count" , arg) ?;
95106
@@ -100,6 +111,17 @@ pub fn bitmap_count_inner(arg: &[ArrayRef]) -> Result<ArrayRef> {
100111 FixedSizeBinary ( _size) => {
101112 downcast_and_count_ones ! ( input_array, FixedSizeBinaryArray )
102113 }
114+ Dictionary ( k, v) if v. as_ref ( ) == & Binary => match k. as_ref ( ) {
115+ DataType :: Int8 => downcast_dict_and_count_ones ! ( input_array, Int8Type ) ,
116+ DataType :: Int16 => downcast_dict_and_count_ones ! ( input_array, Int16Type ) ,
117+ DataType :: Int32 => downcast_dict_and_count_ones ! ( input_array, Int32Type ) ,
118+ DataType :: Int64 => downcast_dict_and_count_ones ! ( input_array, Int64Type ) ,
119+ data_type => {
120+ internal_err ! (
121+ "bitmap_count does not support Dictionary({data_type}, Binary)"
122+ )
123+ }
124+ } ,
103125 data_type => {
104126 internal_err ! ( "bitmap_count does not support {data_type}" )
105127 }
@@ -114,8 +136,12 @@ mod tests {
114136 use crate :: function:: utils:: test:: test_scalar_function;
115137 use arrow:: array:: { Array , Int64Array } ;
116138 use arrow:: datatypes:: DataType :: Int64 ;
139+ use arrow:: datatypes:: { DataType , Field } ;
140+ use datafusion_common:: config:: ConfigOptions ;
117141 use datafusion_common:: { Result , ScalarValue } ;
118- use datafusion_expr:: { ColumnarValue , ScalarUDFImpl } ;
142+ use datafusion_expr:: ColumnarValue :: Scalar ;
143+ use datafusion_expr:: { ColumnarValue , ScalarFunctionArgs , ScalarUDFImpl } ;
144+ use std:: sync:: Arc ;
119145
120146 macro_rules! test_bitmap_count_binary_invoke {
121147 ( $INPUT: expr, $EXPECTED: expr) => {
@@ -171,4 +197,31 @@ mod tests {
171197 ) ;
172198 Ok ( ( ) )
173199 }
200+
201+ #[ test]
202+ fn test_dictionary_encoded_bitmap_count_invoke ( ) -> Result < ( ) > {
203+ let dict = Scalar ( ScalarValue :: Dictionary (
204+ Box :: new ( DataType :: Int32 ) ,
205+ Box :: new ( ScalarValue :: Binary ( Some ( vec ! [ 0xFFu8 , 0xFFu8 ] ) ) ) ,
206+ ) ) ;
207+
208+ let arg_fields = vec ! [ Field :: new(
209+ "a" ,
210+ DataType :: Dictionary ( Box :: new( DataType :: Int32 ) , Box :: new( DataType :: Binary ) ) ,
211+ true ,
212+ )
213+ . into( ) ] ;
214+ let args = ScalarFunctionArgs {
215+ args : vec ! [ dict. clone( ) ] ,
216+ arg_fields,
217+ number_rows : 1 ,
218+ return_field : Field :: new ( "f" , Int64 , true ) . into ( ) ,
219+ config_options : Arc :: new ( ConfigOptions :: default ( ) ) ,
220+ } ;
221+ let udf = BitmapCount :: new ( ) ;
222+ let actual = udf. invoke_with_args ( args) ?;
223+ let expect = Scalar ( ScalarValue :: Int64 ( Some ( 16 ) ) ) ;
224+ assert_eq ! ( * actual. into_array( 1 ) ?, * expect. into_array( 1 ) ?) ;
225+ Ok ( ( ) )
226+ }
174227}
0 commit comments