@@ -205,10 +205,15 @@ impl CaseExpr {
205205 let mut current_value = new_null_array ( & return_type, batch. num_rows ( ) ) ;
206206 // We only consider non-null values while comparing with whens
207207 let mut remainder = not ( & base_nulls) ?;
208+ let mut non_null_remainder_count = remainder. true_count ( ) ;
208209 for i in 0 ..self . when_then_expr . len ( ) {
209- let when_value = self . when_then_expr [ i]
210- . 0
211- . evaluate_selection ( batch, & remainder) ?;
210+ // If there are no rows left to process, break out of the loop early
211+ if non_null_remainder_count == 0 {
212+ break ;
213+ }
214+
215+ let when_predicate = & self . when_then_expr [ i] . 0 ;
216+ let when_value = when_predicate. evaluate_selection ( batch, & remainder) ?;
212217 let when_value = when_value. into_array ( batch. num_rows ( ) ) ?;
213218 // build boolean array representing which rows match the "when" value
214219 let when_match = compare_with_eq (
@@ -224,41 +229,46 @@ impl CaseExpr {
224229 _ => Cow :: Owned ( prep_null_mask_filter ( & when_match) ) ,
225230 } ;
226231 // Make sure we only consider rows that have not been matched yet
227- let when_match = and ( & when_match, & remainder) ?;
232+ let when_value = and ( & when_match, & remainder) ?;
228233
229- // When no rows available for when clause, skip then clause
230- if when_match. true_count ( ) == 0 {
234+ // If the predicate did not match any rows, continue to the next branch immediately
235+ let when_match_count = when_value. true_count ( ) ;
236+ if when_match_count == 0 {
231237 continue ;
232238 }
233239
234- let then_value = self . when_then_expr [ i]
235- . 1
236- . evaluate_selection ( batch, & when_match) ?;
240+ let then_expression = & self . when_then_expr [ i] . 1 ;
241+ let then_value = then_expression. evaluate_selection ( batch, & when_value) ?;
237242
238243 current_value = match then_value {
239244 ColumnarValue :: Scalar ( ScalarValue :: Null ) => {
240- nullif ( current_value. as_ref ( ) , & when_match ) ?
245+ nullif ( current_value. as_ref ( ) , & when_value ) ?
241246 }
242247 ColumnarValue :: Scalar ( then_value) => {
243- zip ( & when_match , & then_value. to_scalar ( ) ?, & current_value) ?
248+ zip ( & when_value , & then_value. to_scalar ( ) ?, & current_value) ?
244249 }
245250 ColumnarValue :: Array ( then_value) => {
246- zip ( & when_match , & then_value, & current_value) ?
251+ zip ( & when_value , & then_value, & current_value) ?
247252 }
248253 } ;
249254
250- remainder = and_not ( & remainder, & when_match) ?;
255+ remainder = and_not ( & remainder, & when_value) ?;
256+ non_null_remainder_count -= when_match_count;
251257 }
252258
253259 if let Some ( e) = self . else_expr ( ) {
254- // keep `else_expr`'s data type and return type consistent
255- let expr = try_cast ( Arc :: clone ( e) , & batch. schema ( ) , return_type. clone ( ) ) ?;
256260 // null and unmatched tuples should be assigned else value
257261 remainder = or ( & base_nulls, & remainder) ?;
258- let else_ = expr
259- . evaluate_selection ( batch, & remainder) ?
260- . into_array ( batch. num_rows ( ) ) ?;
261- current_value = zip ( & remainder, & else_, & current_value) ?;
262+
263+ if remainder. true_count ( ) > 0 {
264+ // keep `else_expr`'s data type and return type consistent
265+ let expr = try_cast ( Arc :: clone ( e) , & batch. schema ( ) , return_type. clone ( ) ) ?;
266+
267+ let else_ = expr
268+ . evaluate_selection ( batch, & remainder) ?
269+ . into_array ( batch. num_rows ( ) ) ?;
270+ current_value = zip ( & remainder, & else_, & current_value) ?;
271+ }
262272 }
263273
264274 Ok ( ColumnarValue :: Array ( current_value) )
@@ -277,10 +287,15 @@ impl CaseExpr {
277287 // start with nulls as default output
278288 let mut current_value = new_null_array ( & return_type, batch. num_rows ( ) ) ;
279289 let mut remainder = BooleanArray :: from ( vec ! [ true ; batch. num_rows( ) ] ) ;
290+ let mut remainder_count = batch. num_rows ( ) ;
280291 for i in 0 ..self . when_then_expr . len ( ) {
281- let when_value = self . when_then_expr [ i]
282- . 0
283- . evaluate_selection ( batch, & remainder) ?;
292+ // If there are no rows left to process, break out of the loop early
293+ if remainder_count == 0 {
294+ break ;
295+ }
296+
297+ let when_predicate = & self . when_then_expr [ i] . 0 ;
298+ let when_value = when_predicate. evaluate_selection ( batch, & remainder) ?;
284299 let when_value = when_value. into_array ( batch. num_rows ( ) ) ?;
285300 let when_value = as_boolean_array ( & when_value) . map_err ( |_| {
286301 internal_datafusion_err ! ( "WHEN expression did not return a BooleanArray" )
@@ -293,14 +308,14 @@ impl CaseExpr {
293308 // Make sure we only consider rows that have not been matched yet
294309 let when_value = and ( & when_value, & remainder) ?;
295310
296- // When no rows available for when clause, skip then clause
297- if when_value. true_count ( ) == 0 {
311+ // If the predicate did not match any rows, continue to the next branch immediately
312+ let when_match_count = when_value. true_count ( ) ;
313+ if when_match_count == 0 {
298314 continue ;
299315 }
300316
301- let then_value = self . when_then_expr [ i]
302- . 1
303- . evaluate_selection ( batch, & when_value) ?;
317+ let then_expression = & self . when_then_expr [ i] . 1 ;
318+ let then_value = then_expression. evaluate_selection ( batch, & when_value) ?;
304319
305320 current_value = match then_value {
306321 ColumnarValue :: Scalar ( ScalarValue :: Null ) => {
@@ -317,10 +332,11 @@ impl CaseExpr {
317332 // Succeed tuples should be filtered out for short-circuit evaluation,
318333 // null values for the current when expr should be kept
319334 remainder = and_not ( & remainder, & when_value) ?;
335+ remainder_count -= when_match_count;
320336 }
321337
322338 if let Some ( e) = self . else_expr ( ) {
323- if remainder . true_count ( ) > 0 {
339+ if remainder_count > 0 {
324340 // keep `else_expr`'s data type and return type consistent
325341 let expr = try_cast ( Arc :: clone ( e) , & batch. schema ( ) , return_type. clone ( ) ) ?;
326342 let else_ = expr
0 commit comments