diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleArrayBlock.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleArrayBlock.java index db8f5904bcdd7..e957a7d124ccc 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleArrayBlock.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleArrayBlock.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.util.List; +import java.util.stream.Collectors; import java.util.stream.Stream; public final class AggregateMetricDoubleArrayBlock extends AbstractNonThreadSafeRefCounted implements AggregateMetricDoubleBlock { @@ -310,4 +311,13 @@ public Block getMetricBlock(int index) { } throw new UnsupportedOperationException("Received an index (" + index + ") outside of range for AggregateMetricDoubleBlock."); } + + @Override + public String toString() { + String valuesString = Stream.of(AggregateMetricDoubleBlockBuilder.Metric.values()) + .map(metric -> metric.getLabel() + "=" + getMetricBlock(metric.getIndex())) + .collect(Collectors.joining(", ", "[", "]")); + + return getClass().getSimpleName() + valuesString; + } } diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockBuilder.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockBuilder.java index 3d1564d93af56..06e7b44a7afb2 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockBuilder.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockBuilder.java @@ -58,6 +58,11 @@ protected int elementSize() { throw new UnsupportedOperationException("Not available on aggregate_metric_double"); } + @Override + public long estimatedBytes() { + return minBuilder.estimatedBytes() + maxBuilder.estimatedBytes() + sumBuilder.estimatedBytes() + countBuilder.estimatedBytes(); + } + @Override public AggregateMetricDoubleBlockBuilder copyFrom(Block b, int beginInclusive, int endExclusive) { Block minBlock; @@ -83,6 +88,35 @@ public AggregateMetricDoubleBlockBuilder copyFrom(Block b, int beginInclusive, i return this; } + public AggregateMetricDoubleBlockBuilder copyFrom(AggregateMetricDoubleBlock block, int position) { + if (block.isNull(position)) { + appendNull(); + return this; + } + + if (block.minBlock().isNull(position)) { + min().appendNull(); + } else { + min().appendDouble(block.minBlock().getDouble(position)); + } + if (block.maxBlock().isNull(position)) { + max().appendNull(); + } else { + max().appendDouble(block.maxBlock().getDouble(position)); + } + if (block.sumBlock().isNull(position)) { + sum().appendNull(); + } else { + sum().appendDouble(block.sumBlock().getDouble(position)); + } + if (block.countBlock().isNull(position)) { + count().appendNull(); + } else { + count().appendInt(block.countBlock().getInt(position)); + } + return this; + } + @Override public AggregateMetricDoubleBlockBuilder appendNull() { minBuilder.appendNull(); diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java index 9e730004ab9f9..2266f02e2716d 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/data/BlockFactory.java @@ -441,30 +441,46 @@ public final AggregateMetricDoubleBlock newConstantAggregateMetricDoubleBlock( int positions ) { try (AggregateMetricDoubleBlockBuilder builder = newAggregateMetricDoubleBlockBuilder(positions)) { - if (value.min() != null) { - builder.min().appendDouble(value.min()); - } else { - builder.min().appendNull(); - } - if (value.max() != null) { - builder.max().appendDouble(value.max()); - } else { - builder.max().appendNull(); - } - if (value.sum() != null) { - builder.sum().appendDouble(value.sum()); - } else { - builder.sum().appendNull(); - } - if (value.count() != null) { - builder.count().appendInt(value.count()); - } else { - builder.count().appendNull(); + for (int i = 0; i < positions; i++) { + if (value.min() != null) { + builder.min().appendDouble(value.min()); + } else { + builder.min().appendNull(); + } + if (value.max() != null) { + builder.max().appendDouble(value.max()); + } else { + builder.max().appendNull(); + } + if (value.sum() != null) { + builder.sum().appendDouble(value.sum()); + } else { + builder.sum().appendNull(); + } + if (value.count() != null) { + builder.count().appendInt(value.count()); + } else { + builder.count().appendNull(); + } } return builder.build(); } } + public final AggregateMetricDoubleBlock newAggregateMetricDoubleBlock( + double[] minValues, + double[] maxValues, + double[] sumValues, + int[] countValues, + int positions + ) { + DoubleBlock min = newDoubleArrayVector(minValues, positions).asBlock(); + DoubleBlock max = newDoubleArrayVector(maxValues, positions).asBlock(); + DoubleBlock sum = newDoubleArrayVector(sumValues, positions).asBlock(); + IntBlock count = newIntArrayVector(countValues, positions).asBlock(); + return new AggregateMetricDoubleArrayBlock(min, max, sum, count); + } + /** * Returns the maximum number of bytes that a Block should be backed by a primitive array before switching to using BigArrays. */ diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockEqualityTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockEqualityTests.java index 1a31ca07e546c..0d17b3aa9e802 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockEqualityTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/AggregateMetricDoubleBlockEqualityTests.java @@ -17,8 +17,6 @@ public class AggregateMetricDoubleBlockEqualityTests extends ComputeTestCase { static final BlockFactory blockFactory = TestBlockFactory.getNonBreakingInstance(); - // TODO: Add additional tests - public void testEmptyBlock() { // all these "empty" blocks should be equivalent var partialMetricBuilder = blockFactory.newAggregateMetricDoubleBlockBuilder(0); @@ -54,6 +52,198 @@ public void testEmptyBlock() { Releasables.close(blocks); } + public void testBlockEqualityRegularBlocks() { + // all these blocks should be equivalent + AggregateMetricDoubleBlockBuilder builder1 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder1, 1.23, 68392.1, 99999.1, 5); + appendValues(builder1, 582.1, 10942, 209301.4, 25); + appendValues(builder1, 8952.564, 30921.23, 18592950.14, 1000); + AggregateMetricDoubleBlockBuilder builder2 = blockFactory.newAggregateMetricDoubleBlockBuilder(6); + appendValues(builder2, 1.23, 68392.1, 99999.1, 5); + appendValues(builder2, 1.23, 68392.1, 99999.1, 10); + appendValues(builder2, 582.1, 10942, 209301.4, 25); + appendValues(builder2, 999.1, 10942, 209301.4, 50); + appendValues(builder2, 10000.564, 30921.23, 18592950.14, 2000); + appendValues(builder2, 8952.564, 30921.23, 18592950.14, 1000); + AggregateMetricDoubleBlockBuilder builder3 = blockFactory.newAggregateMetricDoubleBlockBuilder(5); + builder3.appendNull(); + builder3.appendNull(); + appendValues(builder3, 1.23, 68392.1, 99999.1, 5); + appendValues(builder3, 582.1, 10942, 209301.4, 25); + appendValues(builder3, 8952.564, 30921.23, 18592950.14, 1000); + builder3.appendNull(); + + List blocks = List.of( + builder1.build(), + builder2.build().filter(0, 2, 5), + builder3.build().filter(2, 3, 4) + ); + assertAllEquals(blocks); + } + + public void testBlockEqualityConstantLikeBlocks() { + // all these blocks should be equivalent + AggregateMetricDoubleBlockBuilder builder1 = blockFactory.newAggregateMetricDoubleBlockBuilder(2); + appendValues(builder1, 12.3, 987.6, 4821.3, 6); + appendValues(builder1, 12.3, 987.6, 4821.3, 6); + AggregateMetricDoubleBlockBuilder builder2 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder2, 12.3, 987.6, 4821.3, 6); + appendValues(builder2, 95.2, 10852.2, 20000.5, 5); + appendValues(builder2, 12.3, 987.6, 4821.3, 6); + appendValues(builder2, 1.1, 2.2, 3.3, 2); + DoubleBlock min1 = blockFactory.newDoubleBlockBuilder(4).appendDouble(12.3).appendDouble(12.3).build(); + DoubleBlock max1 = blockFactory.newDoubleBlockBuilder(4).appendDouble(987.6).appendDouble(987.6).build(); + DoubleBlock sum1 = blockFactory.newDoubleBlockBuilder(4).appendDouble(4821.3).appendDouble(4821.3).build(); + IntBlock count1 = blockFactory.newIntBlockBuilder(4).appendInt(6).appendInt(6).build(); + CompositeBlock compositeBlock1 = new CompositeBlock(new Block[] { min1, max1, sum1, count1 }); + DoubleBlock min2 = blockFactory.newDoubleBlockBuilder(4) + .appendDouble(591.1) + .appendDouble(11.1) + .appendDouble(12.3) + .appendDouble(12.3) + .build(); + DoubleBlock max2 = blockFactory.newDoubleBlockBuilder(4) + .appendDouble(198441.1) + .appendDouble(89235982.1) + .appendDouble(987.6) + .appendDouble(987.6) + .build(); + DoubleBlock sum2 = blockFactory.newDoubleBlockBuilder(4) + .appendDouble(13498198.2) + .appendDouble(4901245982.1) + .appendDouble(4821.3) + .appendDouble(4821.3) + .build(); + IntBlock count2 = blockFactory.newIntBlockBuilder(4).appendInt(100).appendInt(200).appendInt(6).appendInt(6).build(); + CompositeBlock compositeBlock2 = new CompositeBlock(new Block[] { min2, max2, sum2, count2 }); + + List moreBlocks = List.of( + builder1.build(), + builder2.build().filter(0, 2), + AggregateMetricDoubleArrayBlock.fromCompositeBlock(compositeBlock1), + AggregateMetricDoubleArrayBlock.fromCompositeBlock(compositeBlock2).filter(2, 3), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(12.3, 987.6, 4821.3, 6), + 4 + ).filter(1, 3), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(12.3, 987.6, 4821.3, 6), + 2 + ) + ); + assertAllEquals(moreBlocks); + } + + public void testBlockEqualityPartialSubmetrics() { + // blocks with partial submetrics appended in different orders (column vs row) + AggregateMetricDoubleBlockBuilder builder1 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + builder1.min().appendDouble(1.23).appendDouble(582.1).appendNull(); + builder1.max().appendDouble(68392.1).appendNull(); + builder1.max().appendDouble(30921.23); + builder1.sum().appendNull(); + builder1.sum().appendDouble(99999.1).appendNull(); + builder1.count().appendNull().appendNull(); + builder1.count().appendInt(1000); + + AggregateMetricDoubleBlockBuilder builder2 = blockFactory.newAggregateMetricDoubleBlockBuilder(6); + builder2.appendNull(); + builder2.appendNull(); + builder2.min().appendDouble(1.23); + builder2.max().appendDouble(68392.1); + builder2.sum().appendNull(); + builder2.count().appendNull(); + builder2.min().appendDouble(582.1); + builder2.max().appendNull(); + builder2.sum().appendDouble(99999.1); + builder2.count().appendNull(); + builder2.appendNull(); + builder2.min().appendNull(); + builder2.max().appendDouble(30921.23); + builder2.sum().appendNull(); + builder2.count().appendInt(1000); + + List evenMoreBlocks = List.of(builder1.build(), builder2.build().filter(2, 3, 5)); + assertAllEquals(evenMoreBlocks); + } + + public void testBlockInequality() { + // all these blocks should NOT be equivalent + AggregateMetricDoubleBlockBuilder builder1 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder1, 1.1, 6.1, 7.2, 2); + builder1.appendNull(); + appendValues(builder1, 1.3, 6.3, 11.9, 3); + // same values as builder1, in a different order + AggregateMetricDoubleBlockBuilder builder2 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder2, 1.3, 6.3, 11.9, 3); + builder2.appendNull(); + appendValues(builder2, 1.1, 6.1, 7.2, 2); + // first 2/3 values match builder1, last 2/3 values match builder2 + AggregateMetricDoubleBlockBuilder builder3 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder3, 1.1, 6.1, 7.2, 2); + builder3.appendNull(); + appendValues(builder3, 1.1, 6.1, 7.2, 2); + // matches the first 2 values of builder1 + AggregateMetricDoubleBlockBuilder builder4 = blockFactory.newAggregateMetricDoubleBlockBuilder(2); + appendValues(builder4, 1.1, 6.1, 7.2, 2); + builder4.appendNull(); + // like builder1 without null value + AggregateMetricDoubleBlockBuilder builder5 = blockFactory.newAggregateMetricDoubleBlockBuilder(2); + appendValues(builder5, 1.1, 6.1, 7.2, 2); + appendValues(builder5, 1.3, 6.3, 11.9, 3); + // like builder1 but first value's sum is null + AggregateMetricDoubleBlockBuilder builder6 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + builder6.min().appendDouble(1.1); + builder6.max().appendDouble(6.1); + builder6.sum().appendNull(); + builder6.count().appendInt(2); + builder6.appendNull(); + appendValues(builder6, 1.3, 6.3, 11.9, 3); + // like builder6 but max and sum are swapped + AggregateMetricDoubleBlockBuilder builder7 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + builder7.min().appendDouble(1.1); + builder7.max().appendNull(); + builder7.sum().appendDouble(6.1); + builder7.count().appendInt(2); + builder7.appendNull(); + appendValues(builder7, 1.3, 6.3, 11.9, 3); + + List notEqualBlocks = List.of( + builder1.build(), + builder2.build(), + builder3.build(), + builder4.build(), + builder5.build(), + builder6.build(), + builder7.build(), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(1.1, 6.1, 7.2, 2), + 1 + ), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(1.1, 6.1, 7.2, 2), + 3 + ) + ); + assertAllNotEquals(notEqualBlocks); + } + + public void testSimpleBlockWithSingleNull() { + AggregateMetricDoubleBlockBuilder builder1 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder1, 1.1, 6.1, 7.2, 2); + builder1.appendNull(); + appendValues(builder1, 1.3, 6.3, 11.9, 3); + AggregateMetricDoubleBlockBuilder builder2 = blockFactory.newAggregateMetricDoubleBlockBuilder(3); + appendValues(builder2, 1.1, 6.1, 7.2, 2); + builder2.appendNull(); + appendValues(builder2, 1.3, 6.3, 11.9, 3); + + List blocks = List.of(builder1.build(), builder2.build()); + + assertEquals(3, blocks.get(0).getPositionCount()); + assertTrue(blocks.get(0).isNull(1)); + assertAllEquals(blocks); + } + public void testSimpleBlockWithManyNulls() { int positions = randomIntBetween(1, 256); boolean grow = randomBoolean(); @@ -86,4 +276,24 @@ static void assertAllEquals(List objs) { } } } + + static void assertAllNotEquals(List objs) { + for (Object obj1 : objs) { + for (Object obj2 : objs) { + if (obj1 == obj2) { + continue; // skip self + } + assertNotEquals(obj1, obj2); + assertNotEquals(obj2, obj1); + assertNotEquals(obj1.hashCode(), obj2.hashCode()); + } + } + } + + static void appendValues(AggregateMetricDoubleBlockBuilder builder, double min, double max, double sum, int count) { + builder.min().appendDouble(min); + builder.max().appendDouble(max); + builder.sum().appendDouble(sum); + builder.count().appendInt(count); + } } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicBlockTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicBlockTests.java index ab8b3ff0f7832..c89d96f10b14c 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicBlockTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicBlockTests.java @@ -99,6 +99,7 @@ void testEmpty(BlockFactory bf) { assertZeroPositionsAndRelease(bf.newBooleanBlockBuilder(0).build()); assertZeroPositionsAndRelease(bf.newBooleanArrayVector(new boolean[] {}, 0)); assertZeroPositionsAndRelease(bf.newBooleanVectorBuilder(0).build()); + assertZeroPositionsAndRelease(bf.newAggregateMetricDoubleBlockBuilder(0).build()); } public void testSmallSingleValueDenseGrowthInt() { @@ -168,6 +169,17 @@ public void testSmallSingleValueDenseGrowthBoolean() { } } + public void testSmallSingleValueDenseGrowthAggregateMetricDouble() { + for (int initialSize : List.of(0, 1, 2, 3, 4, 5)) { + try (var blockBuilder = blockFactory.newBooleanBlockBuilder(initialSize)) { + IntStream.range(0, 10).forEach(i -> blockBuilder.appendBoolean(i % 3 == 0)); + BooleanBlock block = blockBuilder.build(); + assertSingleValueDenseBlock(block); + block.close(); + } + } + } + static void assertSingleValueDenseBlock(Block initialBlock) { final int positionCount = initialBlock.getPositionCount(); int depth = randomIntBetween(1, 5); diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicPageTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicPageTests.java index 99b24d39fe8b1..55b39766ca350 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicPageTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BasicPageTests.java @@ -137,7 +137,7 @@ public void testEqualityAndHashCode() throws IOException { int blockCount = randomIntBetween(1, 256); Block[] blocks = new Block[blockCount]; for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) { - blocks[blockIndex] = switch (randomInt(7)) { + blocks[blockIndex] = switch (randomInt(9)) { case 0 -> blockFactory.newIntArrayVector(randomInts(positions).toArray(), positions).asBlock(); case 1 -> blockFactory.newLongArrayVector(randomLongs(positions).toArray(), positions).asBlock(); case 2 -> blockFactory.newFloatArrayVector(randomFloats(positions), positions).asBlock(); @@ -146,6 +146,23 @@ public void testEqualityAndHashCode() throws IOException { case 5 -> blockFactory.newConstantLongBlockWith(randomLong(), positions); case 6 -> blockFactory.newConstantDoubleBlockWith(randomDouble(), positions); case 7 -> blockFactory.newConstantBytesRefBlockWith(new BytesRef(Integer.toHexString(randomInt())), positions); + case 8 -> blockFactory.newAggregateMetricDoubleBlock( + randomDoubles(positions).toArray(), + randomDoubles(positions).toArray(), + randomDoubles(positions).toArray(), + randomInts(positions).toArray(), + positions + ); + case 9 -> blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomInt() + ), + positions + ); + default -> throw new AssertionError(); }; } @@ -189,10 +206,26 @@ public void testPageSerializationSimple() throws IOException { blockFactory.newFloatArrayVector(randomFloats(10), 10).asBlock(), blockFactory.newDoubleArrayVector(LongStream.range(30, 40).mapToDouble(i -> i).toArray(), 10).asBlock(), blockFactory.newBytesRefArrayVector(bytesRefArrayOf("0a", "1b", "2c", "3d", "4e", "5f", "6g", "7h", "8i", "9j"), 10).asBlock(), + blockFactory.newAggregateMetricDoubleBlock( + randomDoubles(10).toArray(), + randomDoubles(10).toArray(), + randomDoubles(10).toArray(), + randomInts(10).toArray(), + 10 + ), blockFactory.newConstantIntBlockWith(randomInt(), 10), blockFactory.newConstantLongBlockWith(randomLong(), 10), blockFactory.newConstantDoubleBlockWith(randomDouble(), 10), blockFactory.newConstantBytesRefBlockWith(new BytesRef(Integer.toHexString(randomInt())), 10), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomInt() + ), + 10 + ), toFilter.filter(5, 6, 7, 8, 9, 10, 11, 12, 13, 14).asBlock() ); toFilter.close(); @@ -221,7 +254,16 @@ public void testSerializationListPages() throws IOException { new Page(blockFactory.newIntArrayVector(randomInts(positions).toArray(), positions).asBlock()), new Page( blockFactory.newLongArrayVector(randomLongs(positions).toArray(), positions).asBlock(), - blockFactory.newConstantDoubleBlockWith(randomInt(), positions) + blockFactory.newConstantDoubleBlockWith(randomInt(), positions), + blockFactory.newConstantAggregateMetricDoubleBlock( + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomInt() + ), + positions + ) ), new Page(blockFactory.newConstantBytesRefBlockWith(new BytesRef("Hello World"), positions)) ); diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderCopyFromTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderCopyFromTests.java index cfaf77dd1e38d..c97e3bf5fc223 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderCopyFromTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderCopyFromTests.java @@ -27,14 +27,15 @@ public class BlockBuilderCopyFromTests extends ESTestCase { public static List params() { List params = new ArrayList<>(); for (ElementType e : ElementType.values()) { - if (e == ElementType.UNKNOWN - || e == ElementType.NULL - || e == ElementType.DOC - || e == ElementType.COMPOSITE - || e == ElementType.AGGREGATE_METRIC_DOUBLE) { + if (e == ElementType.UNKNOWN || e == ElementType.NULL || e == ElementType.DOC || e == ElementType.COMPOSITE) { continue; } for (boolean nullAllowed : new boolean[] { false, true }) { + if (e == ElementType.AGGREGATE_METRIC_DOUBLE) { + // doesn't support multi-values + params.add(new Object[] { e, nullAllowed, 0, 1 }); + continue; + } for (int[] valuesPerPosition : new int[][] { new int[] { 1, 1 }, new int[] { 1, 10 } }) { // TODO 0 params.add(new Object[] { e, nullAllowed, valuesPerPosition[0], valuesPerPosition[1] }); } @@ -104,6 +105,10 @@ private void assertEvens(Block block) { case FLOAT -> ((FloatBlockBuilder) builder).copyFrom((FloatBlock) block, i); case INT -> ((IntBlockBuilder) builder).copyFrom((IntBlock) block, i); case LONG -> ((LongBlockBuilder) builder).copyFrom((LongBlock) block, i); + case AGGREGATE_METRIC_DOUBLE -> ((AggregateMetricDoubleBlockBuilder) builder).copyFrom( + (AggregateMetricDoubleBlock) block, + i + ); default -> throw new IllegalArgumentException("unsupported type: " + elementType); } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java index c8e1ece222b63..60c2d7dc0276c 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockBuilderTests.java @@ -33,11 +33,7 @@ public class BlockBuilderTests extends ESTestCase { public static List params() { List params = new ArrayList<>(); for (ElementType e : ElementType.values()) { - if (e == ElementType.UNKNOWN - || e == ElementType.NULL - || e == ElementType.DOC - || e == ElementType.COMPOSITE - || e == ElementType.AGGREGATE_METRIC_DOUBLE) { + if (e == ElementType.UNKNOWN || e == ElementType.NULL || e == ElementType.DOC || e == ElementType.COMPOSITE) { continue; } params.add(new Object[] { e }); @@ -102,18 +98,22 @@ public void testBuildHugeSingleValuedNullable() { } public void testBuildSmallMultiValued() { + assumeMultiValued(); testBuild(between(1, 100), false, 3); } public void testBuildHugeMultiValued() { + assumeMultiValued(); testBuild(between(1_000, 50_000), false, 3); } public void testBuildSmallMultiValuedNullable() { + assumeMultiValued(); testBuild(between(1, 100), true, 3); } public void testBuildHugeMultiValuedNullable() { + assumeMultiValued(); testBuild(between(1_000, 50_000), true, 3); } @@ -183,7 +183,9 @@ public void testCrankyConstantBlock() { RandomBlock random = RandomBlock.randomBlock(elementType, 1, false, 1, 1, 0, 0); builder.copyFrom(random.block(), 0, random.block().getPositionCount()); try (Block built = builder.build()) { - assertThat(built.asVector().isConstant(), is(true)); + if (built instanceof AggregateMetricDoubleArrayBlock == false) { + assertThat(built.asVector().isConstant(), is(true)); + } assertThat(built, equalTo(random.block())); } } @@ -195,4 +197,8 @@ public void testCrankyConstantBlock() { assertThat(blockFactory.breaker().getUsed(), equalTo(0L)); } } + + private void assumeMultiValued() { + assumeTrue("Type must support multi-values", elementType != ElementType.AGGREGATE_METRIC_DOUBLE); + } } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockSerializationTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockSerializationTests.java index c186675296cf1..bf00094779588 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockSerializationTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockSerializationTests.java @@ -123,6 +123,13 @@ public void testEmptyBytesRefBlock() throws IOException { } } + public void testEmptyAggregateMetricDoubleBlock() throws IOException { + assertEmptyBlock(blockFactory.newAggregateMetricDoubleBlockBuilder(0).build()); + try (AggregateMetricDoubleBlock toFilter = blockFactory.newAggregateMetricDoubleBlockBuilder(0).appendNull().build()) { + assertEmptyBlock(toFilter.filter()); + } + } + private void assertEmptyBlock(Block origBlock) throws IOException { assertThat(origBlock.getPositionCount(), is(0)); try (origBlock; Block deserBlock = serializeDeserializeBlock(origBlock)) { @@ -221,6 +228,35 @@ public void testFilterBytesRefBlock() throws IOException { } } + public void testFilterAggregateMetricDoubleBlock() throws IOException { + { + var builder = blockFactory.newAggregateMetricDoubleBlockBuilder(0); + builder.min().appendDouble(randomDouble()); + builder.max().appendDouble(randomDouble()); + builder.sum().appendDouble(randomDouble()); + builder.count().appendInt(randomInt()); + builder.min().appendDouble(randomDouble()); + builder.max().appendDouble(randomDouble()); + builder.sum().appendDouble(randomDouble()); + builder.count().appendInt(randomInt()); + try (AggregateMetricDoubleBlock toFilter = builder.build()) { + assertFilterBlock(toFilter.filter(randomIntBetween(0, 1))); + } + } + + { + var builder = blockFactory.newAggregateMetricDoubleBlockBuilder(0); + builder.min().appendDouble(randomDouble()); + builder.max().appendDouble(randomDouble()); + builder.sum().appendDouble(randomDouble()); + builder.count().appendInt(randomInt()); + builder.appendNull(); + try (AggregateMetricDoubleBlock toFilter = builder.build()) { + assertFilterBlock(toFilter.filter(randomIntBetween(0, 1))); + } + } + } + private void assertFilterBlock(Block origBlock) throws IOException { assertThat(origBlock.getPositionCount(), is(1)); try (origBlock; Block deserBlock = serializeDeserializeBlock(origBlock)) { diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockValueAsserter.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockValueAsserter.java index f9c88a504d53d..82117eed95616 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockValueAsserter.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/BlockValueAsserter.java @@ -36,6 +36,12 @@ static void assertBlockValues(Block block, List> expectedBlockValue case DOUBLE -> assertDoubleRowValues((DoubleBlock) block, firstValueIndex, valueCount, expectedRowValues); case BYTES_REF -> assertBytesRefRowValues((BytesRefBlock) block, firstValueIndex, valueCount, expectedRowValues); case BOOLEAN -> assertBooleanRowValues((BooleanBlock) block, firstValueIndex, valueCount, expectedRowValues); + case AGGREGATE_METRIC_DOUBLE -> assertAggregateMetricRowValues( + (AggregateMetricDoubleBlock) block, + firstValueIndex, + valueCount, + expectedRowValues + ); default -> throw new IllegalArgumentException("Unsupported element type [" + block.elementType() + "]"); } } @@ -95,4 +101,20 @@ private static void assertBooleanRowValues(BooleanBlock block, int firstValueInd assertThat(block.getBoolean(firstValueIndex + valueIndex), is(equalTo(expectedValue))); } } + + private static void assertAggregateMetricRowValues( + AggregateMetricDoubleBlock block, + int firstValueIndex, + int valueCount, + List expectedRowValues + ) { + for (int valueIndex = 0; valueIndex < valueCount; valueIndex++) { + AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral expectedValue = + (AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral) expectedRowValues.get(valueIndex); + assertThat(block.minBlock().getDouble(firstValueIndex + valueIndex), is(equalTo(expectedValue.min()))); + assertThat(block.maxBlock().getDouble(firstValueIndex + valueIndex), is(equalTo(expectedValue.max()))); + assertThat(block.sumBlock().getDouble(firstValueIndex + valueIndex), is(equalTo(expectedValue.sum()))); + assertThat(block.countBlock().getInt(firstValueIndex + valueIndex), is(equalTo(expectedValue.count()))); + } + } } diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/FilteredBlockTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/FilteredBlockTests.java index b57819383bfbd..f7894a1fb1db6 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/FilteredBlockTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/data/FilteredBlockTests.java @@ -273,6 +273,24 @@ public void testFilterToStringSimple() { Releasables.close(obj); } Releasables.close(bytesRefVector, bytesRefBlock); + + var aggregateMetricDoubleBlock = blockFactory.newAggregateMetricDoubleBlock( + new double[] { 1.1, 2.2, 3.3, 4.4 }, + new double[] { 5.5, 6.6, 7.7, 8.8 }, + new double[] { 9.9, 10.1, 11.11, 12.12 }, + new int[] { 10, 20, 30, 40 }, + 4 + ); + for (Releasable obj : List.of(aggregateMetricDoubleBlock.filter(0, 2))) { + String s = obj.toString(); + assertThat(s, containsString("[1.1, 3.3]")); + assertThat(s, containsString("[5.5, 7.7]")); + assertThat(s, containsString("[9.9, 11.11]")); + assertThat(s, containsString("[10, 30]")); + assertThat(s, containsString("positions=2")); + Releasables.close(obj); + } + Releasables.close(aggregateMetricDoubleBlock); } public void testFilterToStringMultiValue() { diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/lookup/RightChunkedLeftJoinTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/lookup/RightChunkedLeftJoinTests.java index c62b95e3e816d..6ad3cab9f1881 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/lookup/RightChunkedLeftJoinTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/lookup/RightChunkedLeftJoinTests.java @@ -226,8 +226,18 @@ public void testRandomCranky() { private void testRandom(BlockFactory factory) { int leftSize = between(100, 10000); - ElementType[] leftColumns = randomArray(1, 10, ElementType[]::new, RandomBlock::randomElementType); - ElementType[] rightColumns = randomArray(1, 10, ElementType[]::new, RandomBlock::randomElementType); + ElementType[] leftColumns = randomArray( + 1, + 10, + ElementType[]::new, + () -> RandomBlock.randomElementExcluding(List.of(ElementType.AGGREGATE_METRIC_DOUBLE)) + ); + ElementType[] rightColumns = randomArray( + 1, + 10, + ElementType[]::new, + () -> RandomBlock.randomElementExcluding(List.of(ElementType.AGGREGATE_METRIC_DOUBLE)) + ); RandomPage left = randomPage(factory, leftColumns, leftSize); try (RightChunkedLeftJoin join = new RightChunkedLeftJoin(left.page, rightColumns.length)) { diff --git a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/topn/TopNOperatorTests.java b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/topn/TopNOperatorTests.java index 0d3ef89bfd03c..2c322e5d9edaf 100644 --- a/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/topn/TopNOperatorTests.java +++ b/x-pack/plugin/esql/compute/src/test/java/org/elasticsearch/compute/operator/topn/TopNOperatorTests.java @@ -531,7 +531,7 @@ public void testCollectAllValues() { encoders.add(DEFAULT_SORTABLE); for (ElementType e : ElementType.values()) { - if (e == ElementType.UNKNOWN || e == COMPOSITE || e == AGGREGATE_METRIC_DOUBLE) { + if (e == ElementType.UNKNOWN || e == COMPOSITE) { continue; } elementTypes.add(e); diff --git a/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/BlockTestUtils.java b/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/BlockTestUtils.java index 99bcae419f231..a4c9e312eeb66 100644 --- a/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/BlockTestUtils.java +++ b/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/BlockTestUtils.java @@ -8,6 +8,8 @@ package org.elasticsearch.compute.test; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlock; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BlockFactory; import org.elasticsearch.compute.data.BlockUtils; @@ -39,6 +41,7 @@ import static org.elasticsearch.test.ESTestCase.randomInt; import static org.elasticsearch.test.ESTestCase.randomIntBetween; import static org.elasticsearch.test.ESTestCase.randomLong; +import static org.elasticsearch.test.ESTestCase.randomNonNegativeInt; import static org.elasticsearch.test.ESTestCase.randomRealisticUnicodeOfCodepointLengthBetween; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; @@ -55,6 +58,12 @@ public static Object randomValue(ElementType e) { case DOUBLE -> randomDouble(); case BYTES_REF -> new BytesRef(randomRealisticUnicodeOfCodepointLengthBetween(0, 5)); // TODO: also test spatial WKB case BOOLEAN -> randomBoolean(); + case AGGREGATE_METRIC_DOUBLE -> new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + randomDouble(), + randomDouble(), + randomDouble(), + randomNonNegativeInt() + ); case DOC -> new BlockUtils.Doc( randomIntBetween(0, 255), // Shard ID should be small and non-negative. randomInt(), @@ -62,7 +71,6 @@ public static Object randomValue(ElementType e) { ); case NULL -> null; case COMPOSITE -> throw new IllegalArgumentException("can't make random values for composite"); - case AGGREGATE_METRIC_DOUBLE -> throw new IllegalArgumentException("can't make random values for aggregate_metric_double"); case UNKNOWN -> throw new IllegalArgumentException("can't make random values for [" + e + "]"); }; } @@ -196,6 +204,14 @@ public static void append(Block.Builder builder, Object value) { return; } } + if (builder instanceof AggregateMetricDoubleBlockBuilder b + && value instanceof AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral aggMetric) { + b.min().appendDouble(aggMetric.min()); + b.max().appendDouble(aggMetric.max()); + b.sum().appendDouble(aggMetric.sum()); + b.count().appendInt(aggMetric.count()); + return; + } if (builder instanceof DocBlock.Builder b && value instanceof BlockUtils.Doc v) { b.appendShard(v.shard()).appendSegment(v.segment()).appendDoc(v.doc()); return; @@ -272,6 +288,19 @@ public static List> valuesAtPositions(Block block, int from, int to case DOUBLE -> ((DoubleBlock) block).getDouble(i++); case BYTES_REF -> ((BytesRefBlock) block).getBytesRef(i++, new BytesRef()); case BOOLEAN -> ((BooleanBlock) block).getBoolean(i++); + case AGGREGATE_METRIC_DOUBLE -> { + AggregateMetricDoubleBlock b = (AggregateMetricDoubleBlock) block; + AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral literal = + new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral( + b.minBlock().getDouble(i), + b.maxBlock().getDouble(i), + b.sumBlock().getDouble(i), + b.countBlock().getInt(i) + ); + i += 1; + yield literal; + + } default -> throw new IllegalArgumentException("unsupported element type [" + block.elementType() + "]"); }); } diff --git a/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/RandomBlock.java b/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/RandomBlock.java index 8b3550261d0f6..b458f1f20254c 100644 --- a/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/RandomBlock.java +++ b/x-pack/plugin/esql/compute/test/src/main/java/org/elasticsearch/compute/test/RandomBlock.java @@ -8,6 +8,7 @@ package org.elasticsearch.compute.test; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.compute.data.AggregateMetricDoubleBlockBuilder; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BlockFactory; import org.elasticsearch.compute.data.BooleanBlock; @@ -37,12 +38,16 @@ public record RandomBlock(List> values, Block block) { * A random {@link ElementType} for which we can build a {@link RandomBlock}. */ public static ElementType randomElementType() { + return randomElementExcluding(List.of()); + } + + public static ElementType randomElementExcluding(List type) { return ESTestCase.randomValueOtherThanMany( e -> e == ElementType.UNKNOWN || e == ElementType.NULL || e == ElementType.DOC || e == ElementType.COMPOSITE - || e == ElementType.AGGREGATE_METRIC_DOUBLE, + || type.contains(e), () -> ESTestCase.randomFrom(ElementType.values()) ); } @@ -138,6 +143,18 @@ public static RandomBlock randomBlock( valuesAtPosition.add(b); ((BooleanBlock.Builder) builder).appendBoolean(b); } + case AGGREGATE_METRIC_DOUBLE -> { + AggregateMetricDoubleBlockBuilder b = (AggregateMetricDoubleBlockBuilder) builder; + double min = ESTestCase.randomDouble(); + double max = ESTestCase.randomDouble(); + double sum = ESTestCase.randomDouble(); + int count = ESTestCase.randomNonNegativeInt(); + b.min().appendDouble(min); + b.max().appendDouble(max); + b.sum().appendDouble(sum); + b.count().appendInt(count); + valuesAtPosition.add(new AggregateMetricDoubleBlockBuilder.AggregateMetricDoubleLiteral(min, max, sum, count)); + } default -> throw new IllegalArgumentException("unsupported element type [" + elementType + "]"); } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java index a90ca7c99cc9a..30936961eae37 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/AnalyzerTests.java @@ -37,6 +37,8 @@ import org.elasticsearch.xpack.esql.core.expression.UnresolvedAttribute; import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.core.type.EsField; +import org.elasticsearch.xpack.esql.core.type.InvalidMappedField; import org.elasticsearch.xpack.esql.core.type.MultiTypeEsField; import org.elasticsearch.xpack.esql.core.type.PotentiallyUnmappedKeywordEsField; import org.elasticsearch.xpack.esql.enrich.ResolvedEnrichPolicy; @@ -121,6 +123,7 @@ import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzer; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.analyzerDefaultMapping; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultEnrichResolution; +import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.defaultInferenceResolution; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.indexWithDateDateNanosUnionType; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.loadMapping; import static org.elasticsearch.xpack.esql.analysis.AnalyzerTestUtils.tsdbIndexResolution; @@ -131,6 +134,7 @@ import static org.elasticsearch.xpack.esql.core.type.DataType.DATE_PERIOD; import static org.elasticsearch.xpack.esql.core.type.DataType.DENSE_VECTOR; import static org.elasticsearch.xpack.esql.core.type.DataType.DOUBLE; +import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; import static org.elasticsearch.xpack.esql.core.type.DataType.UNSUPPORTED; import static org.elasticsearch.xpack.esql.type.EsqlDataTypeConverter.dateTimeToString; @@ -4248,6 +4252,66 @@ private void verifyNameAndType(String actualName, DataType actualType, String ex assertEquals(expectedType, actualType); } + public void testImplicitCastingForAggregateMetricDouble() { + assumeTrue( + "aggregate metric double implicit casting must be available", + EsqlCapabilities.Cap.AGGREGATE_METRIC_DOUBLE_IMPLICIT_CASTING_IN_AGGS.isEnabled() + ); + Map mapping = Map.of( + "@timestamp", + new EsField("@timestamp", DATETIME, Map.of(), true, EsField.TimeSeriesFieldType.NONE), + "cluster", + new EsField("cluster", KEYWORD, Map.of(), true, EsField.TimeSeriesFieldType.DIMENSION), + "metric_field", + new InvalidMappedField("metric_field", Map.of("aggregate_metric_double", Set.of("k8s-downsampled"), "double", Set.of("k8s"))) + ); + + var esIndex = new EsIndex( + "k8s*", + mapping, + Map.of("k8s", IndexMode.TIME_SERIES, "k8s-downsampled", IndexMode.TIME_SERIES), + Set.of() + ); + var indexResolution = IndexResolution.valid(esIndex); + var analyzer = new Analyzer( + new AnalyzerContext( + EsqlTestUtils.TEST_CFG, + new EsqlFunctionRegistry(), + indexResolution, + defaultEnrichResolution(), + defaultInferenceResolution() + ), + TEST_VERIFIER + ); + var e = expectThrows(VerificationException.class, () -> analyze(""" + from k8s* | stats std_dev(metric_field) + """, analyzer)); + assertThat( + e.getMessage(), + containsString("Cannot use field [metric_field] due to ambiguities being mapped as [2] incompatible types") + ); + + var plan = analyze(""" + from k8s* | stats max = max(metric_field), + avg = avg(metric_field), + sum = sum(metric_field), + min = min(metric_field), + count = count(metric_field) + """, analyzer); + assertProjection(plan, "max", "avg", "sum", "min", "count"); + + assumeTrue("Metrics command must be available for TS", EsqlCapabilities.Cap.METRICS_COMMAND.isEnabled()); + var plan2 = analyze(""" + TS k8s* | stats s1 = sum(sum_over_time(metric_field)), + s2 = sum(avg_over_time(metric_field)), + min = min(max_over_time(metric_field)), + count = count(count_over_time(metric_field)), + avg = avg(min_over_time(metric_field)) + by cluster, time_bucket = bucket(@timestamp,1minute) + """, analyzer); + assertProjection(plan2, "s1", "s2", "min", "count", "avg", "cluster", "time_bucket"); + } + private void verifyNameAndTypeAndMultiTypeEsField( String actualName, DataType actualType, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/completion/CompletionOperatorOutputBuilderTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/completion/CompletionOperatorOutputBuilderTests.java index 09aabe5fef6e9..885a43b8c18c6 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/completion/CompletionOperatorOutputBuilderTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/completion/CompletionOperatorOutputBuilderTests.java @@ -10,6 +10,7 @@ import org.apache.lucene.util.BytesRef; import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.BytesRefBlock; +import org.elasticsearch.compute.data.ElementType; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.test.ComputeTestCase; import org.elasticsearch.compute.test.RandomBlock; @@ -71,7 +72,7 @@ private Page randomInputPage(int positionCount, int columnCount) { for (int i = 0; i < columnCount; i++) { blocks[i] = RandomBlock.randomBlock( blockFactory(), - RandomBlock.randomElementType(), + RandomBlock.randomElementExcluding(List.of(ElementType.AGGREGATE_METRIC_DOUBLE)), positionCount, randomBoolean(), 0, diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/rerank/RerankOperatorOutputBuilderTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/rerank/RerankOperatorOutputBuilderTests.java index bc204728ff96d..ce3eb5a96fb41 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/rerank/RerankOperatorOutputBuilderTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/inference/rerank/RerankOperatorOutputBuilderTests.java @@ -9,6 +9,7 @@ import org.elasticsearch.compute.data.Block; import org.elasticsearch.compute.data.DoubleBlock; +import org.elasticsearch.compute.data.ElementType; import org.elasticsearch.compute.data.Page; import org.elasticsearch.compute.test.ComputeTestCase; import org.elasticsearch.compute.test.RandomBlock; @@ -84,7 +85,7 @@ private Page randomInputPage(int positionCount, int columnCount) { for (int i = 0; i < columnCount; i++) { blocks[i] = RandomBlock.randomBlock( blockFactory(), - RandomBlock.randomElementType(), + RandomBlock.randomElementExcluding(List.of(ElementType.AGGREGATE_METRIC_DOUBLE)), positionCount, randomBoolean(), 0,