瀏覽代碼

Replace generated fold for `length` (ESQL-1080)

This replaces the generated `fold` call for `length` by calling a
"funny" evaluator that always folds it's targets. Which is always true
before we call `fold`.

The idea here is to remove all of the fancy `fold` implementations we
generate. It's a bit complex to maintain and we don't need it if we go
this direction. This direction is marginally slower, but I don't imagine
that's a big deal.
Nik Everett 2 年之前
父節點
當前提交
128c329d71
共有 15 個文件被更改,包括 99 次插入92 次删除
  1. 42 0
      x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockUtils.java
  2. 6 24
      x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockTestUtils.java
  3. 1 1
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java
  4. 1 9
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Split.java
  5. 14 0
      x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/Mappable.java
  6. 3 36
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractFunctionTestCase.java
  7. 6 5
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java
  8. 2 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/PowTests.java
  9. 3 2
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/RoundTests.java
  10. 3 2
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java
  11. 3 2
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/ConcatTests.java
  12. 8 7
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LengthTests.java
  13. 2 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/SplitTests.java
  14. 2 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/SubstringTests.java
  15. 3 1
      x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/AbstractBinaryOperatorTestCase.java

+ 42 - 0
x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockUtils.java

@@ -10,6 +10,7 @@ package org.elasticsearch.compute.data;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.common.lucene.BytesRefs;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.Consumer;
@@ -190,4 +191,45 @@ public final class BlockUtils {
         }
     }
 
+    /**
+     * Returned by {@link #toJavaObject} for "doc" type blocks.
+     */
+    public record Doc(int shard, int segment, int doc) {}
+
+    /**
+     * Read all values from a positions into a java object. This is not fast
+     * but fine to call in the "fold" path.
+     */
+    public static Object toJavaObject(Block block, int position) {
+        if (block.isNull(position)) {
+            return null;
+        }
+        int count = block.getValueCount(position);
+        int start = block.getFirstValueIndex(position);
+        if (count == 1) {
+            return valueAtOffset(block, start);
+        }
+        int end = start + count;
+        List<Object> result = new ArrayList<>(count);
+        for (int i = start; i < end; i++) {
+            result.add(valueAtOffset(block, i));
+        }
+        return result;
+    }
+
+    private static Object valueAtOffset(Block block, int offset) {
+        return switch (block.elementType()) {
+            case BOOLEAN -> ((BooleanBlock) block).getBoolean(offset);
+            case BYTES_REF -> ((BytesRefBlock) block).getBytesRef(offset, new BytesRef());
+            case DOUBLE -> ((DoubleBlock) block).getDouble(offset);
+            case INT -> ((IntBlock) block).getInt(offset);
+            case LONG -> ((LongBlock) block).getLong(offset);
+            case NULL -> null;
+            case DOC -> {
+                DocVector v = ((DocBlock) block).asVector();
+                yield new Doc(v.shards().getInt(offset), v.segments().getInt(offset), v.docs().getInt(offset));
+            }
+            case UNKNOWN -> throw new IllegalArgumentException("can't read values from [" + block + "]");
+        };
+    }
 }

+ 6 - 24
x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockTestUtils.java

@@ -12,6 +12,7 @@ import org.apache.lucene.util.BytesRef;
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.elasticsearch.test.ESTestCase.between;
 import static org.elasticsearch.test.ESTestCase.randomAlphaOfLength;
 import static org.elasticsearch.test.ESTestCase.randomBoolean;
@@ -20,8 +21,6 @@ import static org.elasticsearch.test.ESTestCase.randomInt;
 import static org.elasticsearch.test.ESTestCase.randomLong;
 
 public class BlockTestUtils {
-    public record Doc(int shard, int segment, int doc) {}
-
     /**
      * Generate a random value of the appropriate type to fit into blocks of {@code e}.
      */
@@ -32,7 +31,7 @@ public class BlockTestUtils {
             case DOUBLE -> randomDouble();
             case BYTES_REF -> new BytesRef(randomAlphaOfLength(5));
             case BOOLEAN -> randomBoolean();
-            case DOC -> new Doc(randomInt(), randomInt(), between(0, Integer.MAX_VALUE));
+            case DOC -> new BlockUtils.Doc(randomInt(), randomInt(), between(0, Integer.MAX_VALUE));
             case NULL -> null;
             case UNKNOWN -> throw new IllegalArgumentException("can't make random values for [" + e + "]");
         };
@@ -55,8 +54,8 @@ public class BlockTestUtils {
             b.appendBytesRef(v);
         } else if (builder instanceof BooleanBlock.Builder b && value instanceof Boolean v) {
             b.appendBoolean(v);
-        } else if (builder instanceof DocBlock.Builder b && value instanceof Doc v) {
-            b.appendShard(v.shard).appendSegment(v.segment).appendDoc(v.doc);
+        } else if (builder instanceof DocBlock.Builder b && value instanceof BlockUtils.Doc v) {
+            b.appendShard(v.shard()).appendSegment(v.segment()).appendDoc(v.doc());
         } else {
             throw new IllegalArgumentException("Can't append [" + value + "/" + value.getClass() + "] to [" + builder + "]");
         }
@@ -78,25 +77,8 @@ public class BlockTestUtils {
     }
 
     public static void readInto(List<Object> values, Block block) {
-        for (int i = 0; i < block.getPositionCount(); i++) {
-            if (block.isNull(i)) {
-                values.add(null);
-            } else if (block instanceof IntBlock b) {
-                values.add(b.getInt(i));
-            } else if (block instanceof LongBlock b) {
-                values.add(b.getLong(i));
-            } else if (block instanceof DoubleBlock b) {
-                values.add(b.getDouble(i));
-            } else if (block instanceof BytesRefBlock b) {
-                values.add(b.getBytesRef(i, new BytesRef()));
-            } else if (block instanceof BooleanBlock b) {
-                values.add(b.getBoolean(i));
-            } else if (block instanceof DocBlock b) {
-                DocVector v = b.asVector();
-                values.add(new Doc(v.shards().getInt(i), v.segments().getInt(i), v.docs().getInt(i)));
-            } else {
-                throw new IllegalArgumentException("can't read values from [" + block + "]");
-            }
+        for (int p = 0; p < block.getPositionCount(); p++) {
+            values.add(toJavaObject(block, p));
         }
     }
 }

+ 1 - 1
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Length.java

@@ -53,7 +53,7 @@ public class Length extends UnaryScalarFunction implements Mappable {
 
     @Override
     public Object fold() {
-        return LengthEvaluator.fold(field());
+        return Mappable.super.fold();
     }
 
     @Evaluator

+ 1 - 9
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/Split.java

@@ -10,9 +10,7 @@ package org.elasticsearch.xpack.esql.expression.function.scalar.string;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.compute.ann.Evaluator;
 import org.elasticsearch.compute.ann.Fixed;
-import org.elasticsearch.compute.data.BlockUtils;
 import org.elasticsearch.compute.data.BytesRefBlock;
-import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
 import org.elasticsearch.xpack.esql.planner.Mappable;
 import org.elasticsearch.xpack.ql.QlIllegalArgumentException;
@@ -25,7 +23,6 @@ import org.elasticsearch.xpack.ql.type.DataTypes;
 
 import java.util.function.Function;
 import java.util.function.Supplier;
-import java.util.stream.IntStream;
 
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.FIRST;
 import static org.elasticsearch.xpack.ql.expression.TypeResolutions.ParamOrdinal.SECOND;
@@ -65,12 +62,7 @@ public class Split extends BinaryScalarFunction implements Mappable {
 
     @Override
     public Object fold() {
-        BytesRefBlock b = (BytesRefBlock) toEvaluator(e -> () -> p -> BlockUtils.fromArrayRow(e.fold())[0]).get().eval(new Page(1));
-        int count = b.getValueCount(0);
-        if (count == 1) {
-            return b.getBytesRef(0, new BytesRef());
-        }
-        return IntStream.range(0, count).mapToObj(i -> b.getBytesRef(i, new BytesRef())).toList();
+        return Mappable.super.fold();
     }
 
     @Evaluator(extraName = "SingleByte")

+ 14 - 0
x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/Mappable.java

@@ -7,15 +7,29 @@
 
 package org.elasticsearch.xpack.esql.planner;
 
+import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
 import org.elasticsearch.xpack.ql.expression.Expression;
 
 import java.util.function.Function;
 import java.util.function.Supplier;
 
+import static org.elasticsearch.compute.data.BlockUtils.fromArrayRow;
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
+
 /**
  * Expressions that have a mapping to an {@link EvalOperator.ExpressionEvaluator}.
  */
 public interface Mappable {
     Supplier<EvalOperator.ExpressionEvaluator> toEvaluator(Function<Expression, Supplier<EvalOperator.ExpressionEvaluator>> toEvaluator);
+
+    /**
+     * Fold using {@link #toEvaluator} so you don't need a "by hand"
+     * implementation of fold. The evaluator that it makes is "funny"
+     * in that it'll always call {@link Expression#fold}, but that's
+     * good enough.
+     */
+    default Object fold() {
+        return toJavaObject(toEvaluator(e -> () -> p -> fromArrayRow(e.fold())[0]).get().eval(new Page(1)), 0);
+    }
 }

+ 3 - 36
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/AbstractFunctionTestCase.java

@@ -12,11 +12,6 @@ import org.apache.lucene.sandbox.document.HalfFloatPoint;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.compute.data.Block;
 import org.elasticsearch.compute.data.BlockUtils;
-import org.elasticsearch.compute.data.BooleanBlock;
-import org.elasticsearch.compute.data.BytesRefBlock;
-import org.elasticsearch.compute.data.DoubleBlock;
-import org.elasticsearch.compute.data.IntBlock;
-import org.elasticsearch.compute.data.LongBlock;
 import org.elasticsearch.compute.data.Page;
 import org.elasticsearch.compute.operator.EvalOperator;
 import org.elasticsearch.test.ESTestCase;
@@ -41,6 +36,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.function.Supplier;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.elasticsearch.xpack.esql.SerializationTestUtils.assertSerialization;
 import static org.hamcrest.Matchers.equalTo;
 
@@ -119,39 +115,10 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
     public final void testSimple() {
         List<Object> simpleData = simpleData();
         Expression expression = expressionForSimpleData();
-        Object result = valueAt(evaluator(expression).get().eval(row(simpleData)), 0);
+        Object result = toJavaObject(evaluator(expression).get().eval(row(simpleData)), 0);
         assertThat(result, resultMatcher(simpleData));
     }
 
-    protected static Object valueAt(Block block, int position) {
-        if (block.isNull(position)) {
-            return null;
-        }
-        int count = block.getValueCount(position);
-        int start = block.getFirstValueIndex(position);
-        if (count == 1) {
-            return valueAtOffset(block, start);
-        }
-        int end = start + count;
-        List<Object> result = new ArrayList<>(count);
-        for (int i = start; i < end; i++) {
-            result.add(valueAtOffset(block, i));
-        }
-        return result;
-    }
-
-    private static Object valueAtOffset(Block block, int offset) {
-        return switch (block.elementType()) {
-            case BOOLEAN -> ((BooleanBlock) block).getBoolean(offset);
-            case BYTES_REF -> ((BytesRefBlock) block).getBytesRef(offset, new BytesRef());
-            case DOUBLE -> ((DoubleBlock) block).getDouble(offset);
-            case INT -> ((IntBlock) block).getInt(offset);
-            case LONG -> ((LongBlock) block).getLong(offset);
-            case NULL -> null;
-            case DOC, UNKNOWN -> throw new IllegalArgumentException();
-        };
-    }
-
     public final void testSimpleWithNulls() {
         List<Object> simpleData = simpleData();
         EvalOperator.ExpressionEvaluator eval = evaluator(expressionForSimpleData()).get();
@@ -191,7 +158,7 @@ public abstract class AbstractFunctionTestCase extends ESTestCase {
                 futures.add(exec.submit(() -> {
                     EvalOperator.ExpressionEvaluator eval = evalSupplier.get();
                     for (int c = 0; c < count; c++) {
-                        assertThat(valueAt(eval.eval(page), 0), resultMatcher);
+                        assertThat(toJavaObject(eval.eval(page), 0), resultMatcher);
                     }
                 }));
             }

+ 6 - 5
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/conditional/CaseTests.java

@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.function.Function;
 import java.util.stream.Stream;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class CaseTests extends AbstractFunctionTestCase {
@@ -60,21 +61,21 @@ public class CaseTests extends AbstractFunctionTestCase {
     @Override
     protected void assertSimpleWithNulls(List<Object> data, Block value, int nullBlock) {
         if (nullBlock == 0) {
-            assertThat(valueAt(value, 0), equalTo(data.get(2)));
+            assertThat(toJavaObject(value, 0), equalTo(data.get(2)));
             return;
         }
         if (((Boolean) data.get(0)).booleanValue()) {
             if (nullBlock == 1) {
                 super.assertSimpleWithNulls(data, value, nullBlock);
             } else {
-                assertThat(valueAt(value, 0), equalTo(data.get(1)));
+                assertThat(toJavaObject(value, 0), equalTo(data.get(1)));
             }
             return;
         }
         if (nullBlock == 2) {
             super.assertSimpleWithNulls(data, value, nullBlock);
         } else {
-            assertThat(valueAt(value, 0), equalTo(data.get(2)));
+            assertThat(toJavaObject(value, 0), equalTo(data.get(2)));
         }
     }
 
@@ -99,7 +100,7 @@ public class CaseTests extends AbstractFunctionTestCase {
 
     public void testEvalCase() {
         testCase(
-            caseExpr -> valueAt(
+            caseExpr -> toJavaObject(
                 caseExpr.toEvaluator(child -> evaluator(child)).get().eval(new Page(IntBlock.newConstantBlockWith(0, 1))),
                 0
             )
@@ -158,7 +159,7 @@ public class CaseTests extends AbstractFunctionTestCase {
 
     public void testCaseIsLazy() {
         Case caseExpr = caseExpr(true, 1, true, 2);
-        assertEquals(1, valueAt(caseExpr.toEvaluator(child -> {
+        assertEquals(1, toJavaObject(caseExpr.toEvaluator(child -> {
             Object value = child.fold();
             if (value != null && value.equals(2)) {
                 return () -> page -> {

+ 2 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/PowTests.java

@@ -17,6 +17,7 @@ import org.hamcrest.Matcher;
 
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class PowTests extends AbstractScalarFunctionTestCase {
@@ -56,7 +57,7 @@ public class PowTests extends AbstractScalarFunctionTestCase {
     }
 
     private Object process(Number base, Number exponent) {
-        return valueAt(
+        return toJavaObject(
             evaluator(new Pow(Source.EMPTY, field("base", typeOf(base)), field("exponent", typeOf(exponent)))).get()
                 .eval(row(List.of(base, exponent))),
             0

+ 3 - 2
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/math/RoundTests.java

@@ -18,6 +18,7 @@ import org.hamcrest.Matcher;
 
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class RoundTests extends AbstractScalarFunctionTestCase {
@@ -60,11 +61,11 @@ public class RoundTests extends AbstractScalarFunctionTestCase {
     }
 
     private Object process(Number val) {
-        return valueAt(evaluator(new Round(Source.EMPTY, field("val", typeOf(val)), null)).get().eval(row(List.of(val))), 0);
+        return toJavaObject(evaluator(new Round(Source.EMPTY, field("val", typeOf(val)), null)).get().eval(row(List.of(val))), 0);
     }
 
     private Object process(Number val, int decimals) {
-        return valueAt(
+        return toJavaObject(
             evaluator(new Round(Source.EMPTY, field("val", typeOf(val)), field("decimals", DataTypes.INTEGER))).get()
                 .eval(row(List.of(val, decimals))),
             0

+ 3 - 2
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/multivalue/AbstractMultivalueFunctionTestCase.java

@@ -21,6 +21,7 @@ import org.hamcrest.Matcher;
 import java.util.List;
 
 import static java.util.Collections.singletonList;
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.hamcrest.Matchers.nullValue;
@@ -76,7 +77,7 @@ public abstract class AbstractMultivalueFunctionTestCase extends AbstractScalarF
             Block result = evaluator(expression).get().eval(new Page(BlockUtils.fromList(data)));
             assertThat(result.asVector(), type == DataTypes.NULL ? nullValue() : notNullValue());
             for (int p = 0; p < data.size(); p++) {
-                assertThat(valueAt(result, p), equalTo(data.get(p).get(0)));
+                assertThat(toJavaObject(result, p), equalTo(data.get(p).get(0)));
             }
         }
     }
@@ -96,7 +97,7 @@ public abstract class AbstractMultivalueFunctionTestCase extends AbstractScalarF
                         assertTrue(type.toString(), result.isNull(p));
                     } else {
                         assertFalse(type.toString(), result.isNull(p));
-                        assertThat(type.toString(), valueAt(result, p), resultMatcherForInput((List<?>) data.get(p).get(0)));
+                        assertThat(type.toString(), toJavaObject(result, p), resultMatcherForInput((List<?>) data.get(p).get(0)));
                     }
                 }
             }

+ 3 - 2
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/ConcatTests.java

@@ -21,6 +21,7 @@ import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class ConcatTests extends AbstractScalarFunctionTestCase {
@@ -89,7 +90,7 @@ public class ConcatTests extends AbstractScalarFunctionTestCase {
     public void testMany() {
         List<Object> simpleData = Stream.of("cats", " ", "and", " ", "dogs").map(s -> (Object) new BytesRef(s)).toList();
         assertThat(
-            valueAt(
+            toJavaObject(
                 evaluator(
                     new Concat(
                         Source.EMPTY,
@@ -106,7 +107,7 @@ public class ConcatTests extends AbstractScalarFunctionTestCase {
     public void testSomeConstant() {
         List<Object> simpleData = Stream.of("cats", "and", "dogs").map(s -> (Object) new BytesRef(s)).toList();
         assertThat(
-            valueAt(
+            toJavaObject(
                 evaluator(
                     new Concat(
                         Source.EMPTY,

+ 8 - 7
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/LengthTests.java

@@ -20,6 +20,7 @@ import org.hamcrest.Matcher;
 
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class LengthTests extends AbstractScalarFunctionTestCase {
@@ -65,12 +66,12 @@ public class LengthTests extends AbstractScalarFunctionTestCase {
 
     public void testExamples() {
         EvalOperator.ExpressionEvaluator eval = evaluator(expressionForSimpleData()).get();
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef("")))), 0), equalTo(0));
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef("a")))), 0), equalTo(1));
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef("clump")))), 0), equalTo(5));
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef("☕")))), 0), equalTo(1));  // 3 bytes, 1 code point
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef("❗️")))), 0), equalTo(2));  // 6 bytes, 2 code points
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef(randomAlphaOfLength(100))))), 0), equalTo(100));
-        assertThat(valueAt(eval.eval(row(List.of(new BytesRef(randomUnicodeOfCodepointLength(100))))), 0), equalTo(100));
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef("")))), 0), equalTo(0));
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef("a")))), 0), equalTo(1));
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef("clump")))), 0), equalTo(5));
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef("☕")))), 0), equalTo(1));  // 3 bytes, 1 code point
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef("❗️")))), 0), equalTo(2));  // 6 bytes, 2 code points
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef(randomAlphaOfLength(100))))), 0), equalTo(100));
+        assertThat(toJavaObject(eval.eval(row(List.of(new BytesRef(randomUnicodeOfCodepointLength(100))))), 0), equalTo(100));
     }
 }

+ 2 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/SplitTests.java

@@ -25,6 +25,7 @@ import java.util.regex.Pattern;
 import java.util.stream.IntStream;
 
 import static java.util.stream.Collectors.joining;
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.equalTo;
 
 public class SplitTests extends AbstractScalarFunctionTestCase {
@@ -91,7 +92,7 @@ public class SplitTests extends AbstractScalarFunctionTestCase {
         assert ':' == 58;
         assertThat(eval.toString(), equalTo("SplitSingleByteEvaluator[str=Attribute[channel=0], delim=58]"));
         assertThat(
-            valueAt(eval.eval(new Page(BytesRefBlock.newConstantBlockWith(new BytesRef("foo:bar"), 1))), 0),
+            toJavaObject(eval.eval(new Page(BytesRefBlock.newConstantBlockWith(new BytesRef("foo:bar"), 1))), 0),
             equalTo(List.of(new BytesRef("foo"), new BytesRef("bar")))
         );
     }

+ 2 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/scalar/string/SubstringTests.java

@@ -19,6 +19,7 @@ import org.hamcrest.Matcher;
 
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.equalTo;
 
@@ -140,7 +141,7 @@ public class SubstringTests extends AbstractScalarFunctionTestCase {
                 length == null ? null : new Literal(Source.EMPTY, length, DataTypes.INTEGER)
             )
         ).get().eval(row(List.of(new BytesRef(str))));
-        return result == null ? null : ((BytesRef) valueAt(result, 0)).utf8ToString();
+        return result == null ? null : ((BytesRef) toJavaObject(result, 0)).utf8ToString();
     }
 
 }

+ 3 - 1
x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/predicate/operator/AbstractBinaryOperatorTestCase.java

@@ -19,6 +19,8 @@ import org.elasticsearch.xpack.ql.type.DataTypes;
 
 import java.util.List;
 
+import static org.elasticsearch.compute.data.BlockUtils.toJavaObject;
+
 public abstract class AbstractBinaryOperatorTestCase extends AbstractFunctionTestCase {
     @Override
     protected final List<Object> simpleData() {
@@ -76,7 +78,7 @@ public abstract class AbstractBinaryOperatorTestCase extends AbstractFunctionTes
                     field("lhs", lhsType),
                     field("rhs", rhsType)
                 );
-                Object result = valueAt(evaluator(op).get().eval(row(List.of(lhs.value(), rhs.value()))), 0);
+                Object result = toJavaObject(evaluator(op).get().eval(row(List.of(lhs.value(), rhs.value()))), 0);
                 assertThat(op.toString(), result, resultMatcher(List.of(lhs.value(), rhs.value())));
             }
         }