3838import org .elasticsearch .xpack .esql .expression .function .scalar .date .DateTrunc ;
3939import org .elasticsearch .xpack .esql .expression .function .scalar .math .Abs ;
4040import org .elasticsearch .xpack .esql .expression .function .scalar .multivalue .MvMin ;
41+ import org .elasticsearch .xpack .esql .expression .function .scalar .nulls .Coalesce ;
4142import org .elasticsearch .xpack .esql .expression .function .scalar .string .RLike ;
4243import org .elasticsearch .xpack .esql .expression .predicate .operator .arithmetic .Add ;
4344import org .elasticsearch .xpack .esql .expression .predicate .operator .comparison .Equals ;
@@ -96,6 +97,9 @@ public class EvalBenchmark {
9697 "add_double" ,
9798 "case_1_eager" ,
9899 "case_1_lazy" ,
100+ "coalesce_2_noop" ,
101+ "coalesce_2_eager" ,
102+ "coalesce_2_lazy" ,
99103 "date_trunc" ,
100104 "equal_to_const" ,
101105 "long_equal_to_long" ,
@@ -142,8 +146,34 @@ private static EvalOperator.ExpressionEvaluator evaluator(String operation) {
142146 lhs = new Add (Source .EMPTY , lhs , new Literal (Source .EMPTY , 1L , DataType .LONG ));
143147 rhs = new Add (Source .EMPTY , rhs , new Literal (Source .EMPTY , 1L , DataType .LONG ));
144148 }
145- yield EvalMapper .toEvaluator (FOLD_CONTEXT , new Case (Source .EMPTY , condition , List .of (lhs , rhs )), layout (f1 , f2 ))
146- .get (driverContext );
149+ EvalOperator .ExpressionEvaluator evaluator = EvalMapper .toEvaluator (
150+ FOLD_CONTEXT ,
151+ new Case (Source .EMPTY , condition , List .of (lhs , rhs )),
152+ layout (f1 , f2 )
153+ ).get (driverContext );
154+ String desc = operation .endsWith ("lazy" ) ? "CaseLazyEvaluator" : "CaseEagerEvaluator" ;
155+ if (evaluator .toString ().contains (desc ) == false ) {
156+ throw new IllegalArgumentException ("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]" );
157+ }
158+ yield evaluator ;
159+ }
160+ case "coalesce_2_noop" , "coalesce_2_eager" , "coalesce_2_lazy" -> {
161+ FieldAttribute f1 = longField ();
162+ FieldAttribute f2 = longField ();
163+ Expression lhs = f1 ;
164+ if (operation .endsWith ("lazy" )) {
165+ lhs = new Add (Source .EMPTY , lhs , new Literal (Source .EMPTY , 1L , DataType .LONG ));
166+ }
167+ EvalOperator .ExpressionEvaluator evaluator = EvalMapper .toEvaluator (
168+ FOLD_CONTEXT ,
169+ new Coalesce (Source .EMPTY , lhs , List .of (f2 )),
170+ layout (f1 , f2 )
171+ ).get (driverContext );
172+ String desc = operation .endsWith ("lazy" ) ? "CoalesceLazyEvaluator" : "CoalesceEagerEvaluator" ;
173+ if (evaluator .toString ().contains (desc ) == false ) {
174+ throw new IllegalArgumentException ("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]" );
175+ }
176+ yield evaluator ;
147177 }
148178 case "date_trunc" -> {
149179 FieldAttribute timestamp = new FieldAttribute (
@@ -260,6 +290,38 @@ private static void checkExpected(String operation, Page actual) {
260290 }
261291 }
262292 }
293+ case "coalesce_2_noop" -> {
294+ LongVector f1 = actual .<LongBlock >getBlock (0 ).asVector ();
295+ LongVector result = actual .<LongBlock >getBlock (2 ).asVector ();
296+ for (int i = 0 ; i < BLOCK_LENGTH ; i ++) {
297+ long expected = f1 .getLong (i );
298+ if (result .getLong (i ) != expected ) {
299+ throw new AssertionError ("[" + operation + "] expected [" + expected + "] but was [" + result .getLong (i ) + "]" );
300+ }
301+ }
302+ }
303+ case "coalesce_2_eager" -> {
304+ LongBlock f1 = actual .<LongBlock >getBlock (0 );
305+ LongVector f2 = actual .<LongBlock >getBlock (1 ).asVector ();
306+ LongVector result = actual .<LongBlock >getBlock (2 ).asVector ();
307+ for (int i = 0 ; i < BLOCK_LENGTH ; i ++) {
308+ long expected = i % 5 == 0 ? f2 .getLong (i ) : f1 .getLong (f1 .getFirstValueIndex (i ));
309+ if (result .getLong (i ) != expected ) {
310+ throw new AssertionError ("[" + operation + "] expected [" + expected + "] but was [" + result .getLong (i ) + "]" );
311+ }
312+ }
313+ }
314+ case "coalesce_2_lazy" -> {
315+ LongBlock f1 = actual .<LongBlock >getBlock (0 );
316+ LongVector f2 = actual .<LongBlock >getBlock (1 ).asVector ();
317+ LongVector result = actual .<LongBlock >getBlock (2 ).asVector ();
318+ for (int i = 0 ; i < BLOCK_LENGTH ; i ++) {
319+ long expected = i % 5 == 0 ? f2 .getLong (i ) : f1 .getLong (f1 .getFirstValueIndex (i )) + 1 ;
320+ if (result .getLong (i ) != expected ) {
321+ throw new AssertionError ("[" + operation + "] expected [" + expected + "] but was [" + result .getLong (i ) + "]" );
322+ }
323+ }
324+ }
263325 case "date_trunc" -> {
264326 LongVector v = actual .<LongBlock >getBlock (1 ).asVector ();
265327 long oneDay = TimeValue .timeValueHours (24 ).millis ();
@@ -304,7 +366,7 @@ private static void checkExpected(String operation, Page actual) {
304366 }
305367 }
306368 }
307- default -> throw new UnsupportedOperationException ();
369+ default -> throw new UnsupportedOperationException (operation );
308370 }
309371 }
310372
@@ -324,7 +386,7 @@ private static Page page(String operation) {
324386 }
325387 yield new Page (builder .build ());
326388 }
327- case "case_1_eager" , "case_1_lazy" -> {
389+ case "case_1_eager" , "case_1_lazy" , "coalesce_2_noop" -> {
328390 var f1 = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
329391 var f2 = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
330392 for (int i = 0 ; i < BLOCK_LENGTH ; i ++) {
@@ -333,6 +395,19 @@ private static Page page(String operation) {
333395 }
334396 yield new Page (f1 .build (), f2 .build ());
335397 }
398+ case "coalesce_2_eager" , "coalesce_2_lazy" -> {
399+ var f1 = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
400+ var f2 = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
401+ for (int i = 0 ; i < BLOCK_LENGTH ; i ++) {
402+ if (i % 5 == 0 ) {
403+ f1 .appendNull ();
404+ } else {
405+ f1 .appendLong (i );
406+ }
407+ f2 .appendLong (-i );
408+ }
409+ yield new Page (f1 .build (), f2 .build ());
410+ }
336411 case "long_equal_to_long" -> {
337412 var lhs = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
338413 var rhs = blockFactory .newLongBlockBuilder (BLOCK_LENGTH );
0 commit comments