Skip to content

Commit 0b807f4

Browse files
committed
Merge branch 'main' into significant-terms-nested-investigation
2 parents 08e6fe5 + 2fabf6a commit 0b807f4

File tree

143 files changed

+9094
-671
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+9094
-671
lines changed

.buildkite/pipelines/periodic-packaging.template.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ steps:
4040
setup:
4141
image:
4242
- windows-2022
43+
- windows-2025
4344
agents:
4445
provider: gcp
4546
image: family/elasticsearch-{{matrix.image}}

.buildkite/pipelines/periodic-packaging.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ steps:
393393
setup:
394394
image:
395395
- windows-2022
396+
- windows-2025
396397
agents:
397398
provider: gcp
398399
image: family/elasticsearch-{{matrix.image}}

.buildkite/pipelines/periodic-platform-support.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ steps:
3838
setup:
3939
image:
4040
- windows-2022
41+
- windows-2025
4142
GRADLE_TASK:
4243
- checkPart1
4344
- checkPart2

.buildkite/pipelines/pull-request/packaging-tests-windows.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ steps:
1111
setup:
1212
image:
1313
- windows-2022
14+
- windows-2025
1415
PACKAGING_TASK:
1516
- default-windows-archive
1617
agents:

benchmarks/src/main/java/org/elasticsearch/benchmark/compute/operator/EvalBenchmark.java

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.common.breaker.NoopCircuitBreaker;
1414
import org.elasticsearch.common.logging.LogConfigurator;
1515
import org.elasticsearch.common.settings.Settings;
16+
import org.elasticsearch.common.unit.ByteSizeUnit;
1617
import org.elasticsearch.common.util.BigArrays;
1718
import org.elasticsearch.compute.data.Block;
1819
import org.elasticsearch.compute.data.BlockFactory;
@@ -44,13 +45,15 @@
4445
import org.elasticsearch.xpack.esql.expression.function.scalar.conditional.Case;
4546
import org.elasticsearch.xpack.esql.expression.function.scalar.date.DateTrunc;
4647
import org.elasticsearch.xpack.esql.expression.function.scalar.math.Abs;
48+
import org.elasticsearch.xpack.esql.expression.function.scalar.math.RoundTo;
4749
import org.elasticsearch.xpack.esql.expression.function.scalar.multivalue.MvMin;
4850
import org.elasticsearch.xpack.esql.expression.function.scalar.nulls.Coalesce;
4951
import org.elasticsearch.xpack.esql.expression.function.scalar.string.RLike;
5052
import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToLower;
5153
import org.elasticsearch.xpack.esql.expression.function.scalar.string.ToUpper;
5254
import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.Add;
5355
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.Equals;
56+
import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThan;
5457
import org.elasticsearch.xpack.esql.planner.Layout;
5558
import org.elasticsearch.xpack.esql.plugin.EsqlPlugin;
5659
import org.elasticsearch.xpack.esql.session.Configuration;
@@ -128,6 +131,10 @@ static void selfTest() {
128131
"long_equal_to_int",
129132
"mv_min",
130133
"mv_min_ascending",
134+
"round_to_4_via_case",
135+
"round_to_2",
136+
"round_to_3",
137+
"round_to_4",
131138
"rlike",
132139
"to_lower",
133140
"to_lower_ords",
@@ -240,6 +247,65 @@ private static EvalOperator.ExpressionEvaluator evaluator(String operation) {
240247
RLike rlike = new RLike(Source.EMPTY, keywordField, new RLikePattern(".ar"));
241248
yield EvalMapper.toEvaluator(FOLD_CONTEXT, rlike, layout(keywordField)).get(driverContext);
242249
}
250+
case "round_to_4_via_case" -> {
251+
FieldAttribute f = longField();
252+
253+
Expression ltkb = new LessThan(Source.EMPTY, f, kb());
254+
Expression ltmb = new LessThan(Source.EMPTY, f, mb());
255+
Expression ltgb = new LessThan(Source.EMPTY, f, gb());
256+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
257+
FOLD_CONTEXT,
258+
new Case(Source.EMPTY, ltkb, List.of(b(), ltmb, kb(), ltgb, mb(), gb())),
259+
layout(f)
260+
).get(driverContext);
261+
String desc = "CaseLazyEvaluator";
262+
if (evaluator.toString().contains(desc) == false) {
263+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
264+
}
265+
yield evaluator;
266+
}
267+
case "round_to_2" -> {
268+
FieldAttribute f = longField();
269+
270+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
271+
FOLD_CONTEXT,
272+
new RoundTo(Source.EMPTY, f, List.of(b(), kb())),
273+
layout(f)
274+
).get(driverContext);
275+
String desc = "RoundToLong2";
276+
if (evaluator.toString().contains(desc) == false) {
277+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
278+
}
279+
yield evaluator;
280+
}
281+
case "round_to_3" -> {
282+
FieldAttribute f = longField();
283+
284+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
285+
FOLD_CONTEXT,
286+
new RoundTo(Source.EMPTY, f, List.of(b(), kb(), mb())),
287+
layout(f)
288+
).get(driverContext);
289+
String desc = "RoundToLong3";
290+
if (evaluator.toString().contains(desc) == false) {
291+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
292+
}
293+
yield evaluator;
294+
}
295+
case "round_to_4" -> {
296+
FieldAttribute f = longField();
297+
298+
EvalOperator.ExpressionEvaluator evaluator = EvalMapper.toEvaluator(
299+
FOLD_CONTEXT,
300+
new RoundTo(Source.EMPTY, f, List.of(b(), kb(), mb(), gb())),
301+
layout(f)
302+
).get(driverContext);
303+
String desc = "RoundToLong4";
304+
if (evaluator.toString().contains(desc) == false) {
305+
throw new IllegalArgumentException("Evaluator was [" + evaluator + "] but expected one containing [" + desc + "]");
306+
}
307+
yield evaluator;
308+
}
243309
case "to_lower", "to_lower_ords" -> {
244310
FieldAttribute keywordField = keywordField();
245311
ToLower toLower = new ToLower(Source.EMPTY, keywordField, configuration());
@@ -419,6 +485,69 @@ private static void checkExpected(String operation, Page actual) {
419485
}
420486
}
421487
}
488+
case "round_to_4_via_case", "round_to_4" -> {
489+
long b = 1;
490+
long kb = ByteSizeUnit.KB.toBytes(1);
491+
long mb = ByteSizeUnit.MB.toBytes(1);
492+
long gb = ByteSizeUnit.GB.toBytes(1);
493+
494+
LongVector f = actual.<LongBlock>getBlock(0).asVector();
495+
LongVector result = actual.<LongBlock>getBlock(1).asVector();
496+
for (int i = 0; i < BLOCK_LENGTH; i++) {
497+
long expected = f.getLong(i);
498+
if (expected < kb) {
499+
expected = b;
500+
} else if (expected < mb) {
501+
expected = kb;
502+
} else if (expected < gb) {
503+
expected = mb;
504+
} else {
505+
expected = gb;
506+
}
507+
if (result.getLong(i) != expected) {
508+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
509+
}
510+
}
511+
}
512+
case "round_to_3" -> {
513+
long b = 1;
514+
long kb = ByteSizeUnit.KB.toBytes(1);
515+
long mb = ByteSizeUnit.MB.toBytes(1);
516+
517+
LongVector f = actual.<LongBlock>getBlock(0).asVector();
518+
LongVector result = actual.<LongBlock>getBlock(1).asVector();
519+
for (int i = 0; i < BLOCK_LENGTH; i++) {
520+
long expected = f.getLong(i);
521+
if (expected < kb) {
522+
expected = b;
523+
} else if (expected < mb) {
524+
expected = kb;
525+
} else {
526+
expected = mb;
527+
}
528+
if (result.getLong(i) != expected) {
529+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
530+
}
531+
}
532+
}
533+
case "round_to_2" -> {
534+
long b = 1;
535+
long kb = ByteSizeUnit.KB.toBytes(1);
536+
537+
LongVector f = actual.<LongBlock>getBlock(0).asVector();
538+
LongVector result = actual.<LongBlock>getBlock(1).asVector();
539+
for (int i = 0; i < BLOCK_LENGTH; i++) {
540+
long expected = f.getLong(i);
541+
if (expected < kb) {
542+
expected = b;
543+
} else {
544+
expected = kb;
545+
}
546+
if (result.getLong(i) != expected) {
547+
throw new AssertionError("[" + operation + "] expected [" + expected + "] but was [" + result.getLong(i) + "]");
548+
}
549+
}
550+
}
422551
case "to_lower" -> checkBytes(operation, actual, false, new BytesRef[] { new BytesRef("foo"), new BytesRef("bar") });
423552
case "to_lower_ords" -> checkBytes(operation, actual, true, new BytesRef[] { new BytesRef("foo"), new BytesRef("bar") });
424553
case "to_upper" -> checkBytes(operation, actual, false, new BytesRef[] { new BytesRef("FOO"), new BytesRef("BAR") });
@@ -450,7 +579,7 @@ private static void checkBytes(String operation, Page actual, boolean expectOrds
450579

451580
private static Page page(String operation) {
452581
return switch (operation) {
453-
case "abs", "add", "date_trunc", "equal_to_const" -> {
582+
case "abs", "add", "date_trunc", "equal_to_const", "round_to_4_via_case", "round_to_2", "round_to_3", "round_to_4" -> {
454583
var builder = blockFactory.newLongBlockBuilder(BLOCK_LENGTH);
455584
for (int i = 0; i < BLOCK_LENGTH; i++) {
456585
builder.appendLong(i * 100_000);
@@ -540,6 +669,26 @@ private static Page page(String operation) {
540669
};
541670
}
542671

672+
private static Literal b() {
673+
return lit(1L);
674+
}
675+
676+
private static Literal kb() {
677+
return lit(ByteSizeUnit.KB.toBytes(1));
678+
}
679+
680+
private static Literal mb() {
681+
return lit(ByteSizeUnit.MB.toBytes(1));
682+
}
683+
684+
private static Literal gb() {
685+
return lit(ByteSizeUnit.GB.toBytes(1));
686+
}
687+
688+
private static Literal lit(long v) {
689+
return new Literal(Source.EMPTY, v, DataType.LONG);
690+
}
691+
543692
@Benchmark
544693
@OperationsPerInvocation(1024 * BLOCK_LENGTH)
545694
public void run() {

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/RestTestBasePlugin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public void apply(Project project) {
165165
nonInputSystemProperties.systemProperty(TESTS_FEATURES_METADATA_PATH, () -> featureMetadataConfig.getAsPath());
166166

167167
// Enable parallel execution for these tests since each test gets its own cluster
168-
task.setMaxParallelForks(task.getProject().getGradle().getStartParameter().getMaxWorkerCount() / 2);
168+
task.setMaxParallelForks(Math.max(1, task.getProject().getGradle().getStartParameter().getMaxWorkerCount() / 2));
169169
nonInputSystemProperties.systemProperty(TESTS_MAX_PARALLEL_FORKS_SYSPROP, () -> String.valueOf(task.getMaxParallelForks()));
170170

171171
// Disable test failure reporting since this stuff is now captured in build scans

build-tools/src/integTest/groovy/org/elasticsearch/gradle/test/TestBuildInfoPluginFuncTest.groovy

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
66
import org.gradle.testkit.runner.TaskOutcome
77

88
class TestBuildInfoPluginFuncTest extends AbstractGradleFuncTest {
9-
def "works"() {
9+
def "basic functionality"() {
1010
given:
1111
file("src/main/java/com/example/Example.java") << """
1212
package com.example;
@@ -60,4 +60,62 @@ class TestBuildInfoPluginFuncTest extends AbstractGradleFuncTest {
6060
)
6161
new ObjectMapper().readValue(output, Map.class) == expectedOutput
6262
}
63+
64+
def "dependencies"() {
65+
buildFile << """
66+
import org.elasticsearch.gradle.plugin.GenerateTestBuildInfoTask;
67+
68+
plugins {
69+
id 'java'
70+
id 'elasticsearch.test-build-info'
71+
}
72+
73+
repositories {
74+
mavenCentral()
75+
}
76+
77+
dependencies {
78+
// We pin to specific versions here because they are known to have the properties we want to test.
79+
// We're not actually running this code.
80+
implementation "org.ow2.asm:asm:9.7.1" // has module-info.class
81+
implementation "junit:junit:4.13" // has Automatic-Module-Name, and brings in hamcrest which does not
82+
}
83+
84+
tasks.withType(GenerateTestBuildInfoTask.class) {
85+
componentName = 'example-component'
86+
outputFile = new File('build/generated-build-info/plugin-test-build-info.json')
87+
}
88+
"""
89+
90+
when:
91+
def result = gradleRunner('generateTestBuildInfo').build()
92+
def task = result.task(":generateTestBuildInfo")
93+
94+
95+
then:
96+
task.outcome == TaskOutcome.SUCCESS
97+
98+
def output = file("build/generated-build-info/plugin-test-build-info.json")
99+
output.exists() == true
100+
101+
def locationFromModuleInfo = Map.of(
102+
"module", "org.objectweb.asm",
103+
"representative_class", 'org/objectweb/asm/AnnotationVisitor.class'
104+
)
105+
def locationFromManifest = Map.of(
106+
"module", "junit",
107+
"representative_class", 'junit/textui/TestRunner.class'
108+
)
109+
def locationFromJarFileName = Map.of(
110+
"module", "hamcrest.core",
111+
"representative_class", 'org/hamcrest/BaseDescription.class'
112+
)
113+
def expectedOutput = Map.of(
114+
"component", "example-component",
115+
"locations", List.of(locationFromModuleInfo, locationFromManifest, locationFromJarFileName)
116+
)
117+
118+
def value = new ObjectMapper().readValue(output, Map.class)
119+
value == expectedOutput
120+
}
63121
}

build-tools/src/main/java/org/elasticsearch/gradle/plugin/GenerateTestBuildInfoTask.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
import java.nio.file.attribute.BasicFileAttributes;
4242
import java.security.CodeSource;
4343
import java.util.ArrayList;
44-
import java.util.Arrays;
44+
import java.util.Comparator;
4545
import java.util.List;
4646
import java.util.jar.JarEntry;
4747
import java.util.jar.JarFile;
@@ -209,17 +209,16 @@ private String extractModuleNameFromJar(File file, JarFile jarFile) throws IOExc
209209
* @return a {@link StringBuilder} with the {@code META-INF/versions/<version number>} if it exists; otherwise null
210210
*/
211211
private static StringBuilder versionDirectoryIfExists(JarFile jarFile) {
212+
Comparator<Integer> numericOrder = Integer::compareTo;
212213
List<Integer> versions = jarFile.stream()
213214
.filter(je -> je.getName().startsWith(META_INF_VERSIONS_PREFIX) && je.getName().endsWith("/module-info.class"))
214215
.map(
215216
je -> Integer.parseInt(
216217
je.getName().substring(META_INF_VERSIONS_PREFIX.length(), je.getName().length() - META_INF_VERSIONS_PREFIX.length())
217218
)
218219
)
220+
.sorted(numericOrder.reversed())
219221
.toList();
220-
versions = new ArrayList<>(versions);
221-
versions.sort(Integer::compareTo);
222-
versions = versions.reversed();
223222
int major = Runtime.version().feature();
224223
StringBuilder path = new StringBuilder(META_INF_VERSIONS_PREFIX);
225224
for (int version : versions) {
@@ -300,7 +299,10 @@ private String extractClassNameFromDirectory(File dir) throws IOException {
300299
public @NotNull FileVisitResult visitFile(@NotNull Path candidate, @NotNull BasicFileAttributes attrs) {
301300
String name = candidate.getFileName().toString(); // Just the part after the last dir separator
302301
if (name.endsWith(".class") && (name.equals("module-info.class") || name.contains("$")) == false) {
303-
result = candidate.toAbsolutePath().toString().substring(dir.getAbsolutePath().length() + 1);
302+
result = candidate.toAbsolutePath()
303+
.toString()
304+
.substring(dir.getAbsolutePath().length() + 1)
305+
.replace(File.separatorChar, '/');
304306
return TERMINATE;
305307
} else {
306308
return CONTINUE;
@@ -316,20 +318,24 @@ private String extractClassNameFromDirectory(File dir) throws IOException {
316318
* if it exists or the preset one derived from the jar task
317319
*/
318320
private String extractModuleNameFromDirectory(File dir) throws IOException {
319-
List<File> files = new ArrayList<>(List.of(dir));
320-
while (files.isEmpty() == false) {
321-
File find = files.removeFirst();
322-
if (find.exists()) {
323-
if (find.getName().equals("module-info.class")) {
324-
try (InputStream inputStream = new FileInputStream(find)) {
325-
return extractModuleNameFromModuleInfo(inputStream);
321+
var visitor = new SimpleFileVisitor<Path>() {
322+
private String result = getModuleName().getOrNull();
323+
324+
@Override
325+
public @NotNull FileVisitResult visitFile(@NotNull Path candidate, @NotNull BasicFileAttributes attrs) throws IOException {
326+
String name = candidate.getFileName().toString(); // Just the part after the last dir separator
327+
if (name.equals("module-info.class")) {
328+
try (InputStream inputStream = new FileInputStream(candidate.toFile())) {
329+
result = extractModuleNameFromModuleInfo(inputStream);
330+
return TERMINATE;
326331
}
327-
} else if (find.isDirectory()) {
328-
files.addAll(Arrays.asList(find.listFiles()));
332+
} else {
333+
return CONTINUE;
329334
}
330335
}
331-
}
332-
return getModuleName().getOrNull();
336+
};
337+
Files.walkFileTree(dir.toPath(), visitor);
338+
return visitor.result;
333339
}
334340

335341
/**

0 commit comments

Comments
 (0)