@@ -40,13 +40,28 @@ use crate::type_check::format_function_argument_mismatch_hint;
4040use crate :: type_check:: get_simple_cast_function;
4141use crate :: types:: BooleanType ;
4242use crate :: types:: DataType ;
43+ use crate :: types:: Decimal64Type ;
44+ use crate :: types:: Decimal128Type ;
45+ use crate :: types:: Decimal256Type ;
4346use crate :: types:: DecimalColumn ;
47+ use crate :: types:: DecimalDataKind ;
4448use crate :: types:: DecimalDataType ;
4549use crate :: types:: F32 ;
50+ use crate :: types:: Float32Type ;
51+ use crate :: types:: Float64Type ;
52+ use crate :: types:: Int8Type ;
53+ use crate :: types:: Int16Type ;
54+ use crate :: types:: Int32Type ;
55+ use crate :: types:: Int64Type ;
4656use crate :: types:: NullableType ;
57+ use crate :: types:: NumberDataType ;
4758use crate :: types:: NumberScalar ;
4859use crate :: types:: ReturnType ;
4960use crate :: types:: StringType ;
61+ use crate :: types:: UInt8Type ;
62+ use crate :: types:: UInt16Type ;
63+ use crate :: types:: UInt32Type ;
64+ use crate :: types:: UInt64Type ;
5065use crate :: types:: ValueType ;
5166use crate :: types:: VariantType ;
5267use crate :: types:: VectorDataType ;
@@ -101,6 +116,131 @@ impl<'a> EvaluateOptions<'a> {
101116 }
102117}
103118
119+ fn select_binary_if_typed < T : ValueType > (
120+ flag : & Bitmap ,
121+ then_result : & Value < AnyType > ,
122+ else_result : & Value < AnyType > ,
123+ data_type : & DataType ,
124+ len : usize ,
125+ ) -> Result < Column > {
126+ let then_result = then_result. try_downcast :: < T > ( ) ?;
127+ let else_result = else_result. try_downcast :: < T > ( ) ?;
128+ let mut output_builder = ColumnBuilder :: with_capacity ( data_type, len) ;
129+
130+ {
131+ let mut output = T :: downcast_builder ( & mut output_builder) ;
132+ match ( & then_result, & else_result) {
133+ ( Value :: Scalar ( then_value) , Value :: Scalar ( else_value) ) => {
134+ let then_value = T :: to_scalar_ref ( then_value) ;
135+ let else_value = T :: to_scalar_ref ( else_value) ;
136+ for take_then in flag. iter ( ) {
137+ let value = if take_then {
138+ then_value. clone ( )
139+ } else {
140+ else_value. clone ( )
141+ } ;
142+ T :: push_item_mut ( & mut output, value) ;
143+ }
144+ }
145+ ( Value :: Scalar ( then_value) , Value :: Column ( else_column) ) => {
146+ let then_value = T :: to_scalar_ref ( then_value) ;
147+ for ( row, take_then) in flag. iter ( ) . enumerate ( ) {
148+ let value = if take_then {
149+ then_value. clone ( )
150+ } else {
151+ unsafe { T :: index_column_unchecked ( else_column, row) }
152+ } ;
153+ T :: push_item_mut ( & mut output, value) ;
154+ }
155+ }
156+ ( Value :: Column ( then_column) , Value :: Scalar ( else_value) ) => {
157+ let else_value = T :: to_scalar_ref ( else_value) ;
158+ for ( row, take_then) in flag. iter ( ) . enumerate ( ) {
159+ let value = if take_then {
160+ unsafe { T :: index_column_unchecked ( then_column, row) }
161+ } else {
162+ else_value. clone ( )
163+ } ;
164+ T :: push_item_mut ( & mut output, value) ;
165+ }
166+ }
167+ ( Value :: Column ( then_column) , Value :: Column ( else_column) ) => {
168+ for ( row, take_then) in flag. iter ( ) . enumerate ( ) {
169+ let value = if take_then {
170+ unsafe { T :: index_column_unchecked ( then_column, row) }
171+ } else {
172+ unsafe { T :: index_column_unchecked ( else_column, row) }
173+ } ;
174+ T :: push_item_mut ( & mut output, value) ;
175+ }
176+ }
177+ }
178+ }
179+
180+ Ok ( output_builder. build ( ) )
181+ }
182+
183+ fn select_binary_numeric_if (
184+ flag : & Bitmap ,
185+ then_result : & Value < AnyType > ,
186+ else_result : & Value < AnyType > ,
187+ data_type : & DataType ,
188+ len : usize ,
189+ ) -> Result < Option < Column > > {
190+ macro_rules! select_plain {
191+ ( $type: ty) => {
192+ select_binary_if_typed:: <$type>( flag, then_result, else_result, data_type, len)
193+ } ;
194+ }
195+ macro_rules! select_nullable {
196+ ( $type: ty) => {
197+ select_binary_if_typed:: <NullableType <$type>>(
198+ flag,
199+ then_result,
200+ else_result,
201+ data_type,
202+ len,
203+ )
204+ } ;
205+ }
206+ macro_rules! select_number {
207+ ( $number_type: expr, $select: ident) => {
208+ match $number_type {
209+ NumberDataType :: UInt8 => $select!( UInt8Type ) ,
210+ NumberDataType :: UInt16 => $select!( UInt16Type ) ,
211+ NumberDataType :: UInt32 => $select!( UInt32Type ) ,
212+ NumberDataType :: UInt64 => $select!( UInt64Type ) ,
213+ NumberDataType :: Int8 => $select!( Int8Type ) ,
214+ NumberDataType :: Int16 => $select!( Int16Type ) ,
215+ NumberDataType :: Int32 => $select!( Int32Type ) ,
216+ NumberDataType :: Int64 => $select!( Int64Type ) ,
217+ NumberDataType :: Float32 => $select!( Float32Type ) ,
218+ NumberDataType :: Float64 => $select!( Float64Type ) ,
219+ }
220+ } ;
221+ }
222+
223+ let column = match data_type {
224+ DataType :: Number ( number_type) => select_number ! ( number_type, select_plain) ?,
225+ DataType :: Decimal ( size) => match size. data_kind ( ) {
226+ DecimalDataKind :: Decimal64 => select_plain ! ( Decimal64Type ) ?,
227+ DecimalDataKind :: Decimal128 => select_plain ! ( Decimal128Type ) ?,
228+ DecimalDataKind :: Decimal256 => select_plain ! ( Decimal256Type ) ?,
229+ } ,
230+ DataType :: Nullable ( inner) => match inner. as_ref ( ) {
231+ DataType :: Number ( number_type) => select_number ! ( number_type, select_nullable) ?,
232+ DataType :: Decimal ( size) => match size. data_kind ( ) {
233+ DecimalDataKind :: Decimal64 => select_nullable ! ( Decimal64Type ) ?,
234+ DecimalDataKind :: Decimal128 => select_nullable ! ( Decimal128Type ) ?,
235+ DecimalDataKind :: Decimal256 => select_nullable ! ( Decimal256Type ) ?,
236+ } ,
237+ _ => return Ok ( None ) ,
238+ } ,
239+ _ => return Ok ( None ) ,
240+ } ;
241+ Ok ( Some ( column) )
242+ }
243+
104244pub struct Evaluator < ' a > {
105245 data_block : & ' a DataBlock ,
106246 func_ctx : & ' a FunctionContext ,
@@ -1641,6 +1781,13 @@ impl<'a> Evaluator<'a> {
16411781 . all_equal( )
16421782 ) ;
16431783
1784+ if let ( Some ( len) , [ flag] , [ then_result] ) = ( len, flags. as_slice ( ) , results. as_slice ( ) )
1785+ && let Some ( column) =
1786+ select_binary_numeric_if ( flag, then_result, & else_result, & generics[ 0 ] , len) ?
1787+ {
1788+ return Ok ( Value :: Column ( column) ) ;
1789+ }
1790+
16441791 // Pick the results from the result branches depending on the condition.
16451792 let mut output_builder = ColumnBuilder :: with_capacity ( & generics[ 0 ] , len. unwrap_or ( 1 ) ) ;
16461793 for row_idx in 0 ..( len. unwrap_or ( 1 ) ) {
0 commit comments