Skip to content

Commit 68620b9

Browse files
authored
Merge branch 'main' into sync-docker-classifier
2 parents d64a920 + afe4492 commit 68620b9

File tree

16 files changed

+238
-188
lines changed

16 files changed

+238
-188
lines changed

docs/changelog/130638.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pr: 130638
2+
summary: Prevent search functions work with a non-STANDARD index
3+
area: ES|QL
4+
type: bug
5+
issues:
6+
- 130561
7+
- 129778

muted-tests.yml

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ tests:
233233
- class: org.elasticsearch.packaging.test.DockerTests
234234
method: test012SecurityCanBeDisabled
235235
issue: https://github.com/elastic/elasticsearch/issues/116636
236-
- class: org.elasticsearch.index.shard.StoreRecoveryTests
237-
method: testAddIndices
238-
issue: https://github.com/elastic/elasticsearch/issues/124104
239236
- class: org.elasticsearch.smoketest.MlWithSecurityIT
240237
method: test {yaml=ml/data_frame_analytics_crud/Test get stats on newly created config}
241238
issue: https://github.com/elastic/elasticsearch/issues/121726
@@ -446,12 +443,6 @@ tests:
446443
- class: org.elasticsearch.packaging.test.DockerTests
447444
method: test073RunEsAsDifferentUserAndGroupWithoutBindMounting
448445
issue: https://github.com/elastic/elasticsearch/issues/128996
449-
- class: org.elasticsearch.upgrades.UpgradeClusterClientYamlTestSuiteIT
450-
method: test {p0=upgraded_cluster/70_ilm/Test Lifecycle Still There And Indices Are Still Managed}
451-
issue: https://github.com/elastic/elasticsearch/issues/129097
452-
- class: org.elasticsearch.upgrades.UpgradeClusterClientYamlTestSuiteIT
453-
method: test {p0=upgraded_cluster/90_ml_data_frame_analytics_crud/Get mixed cluster outlier_detection job}
454-
issue: https://github.com/elastic/elasticsearch/issues/129098
455446
- class: org.elasticsearch.packaging.test.DockerTests
456447
method: test081SymlinksAreFollowedWithEnvironmentVariableFiles
457448
issue: https://github.com/elastic/elasticsearch/issues/128867
@@ -473,15 +464,6 @@ tests:
473464
- class: org.elasticsearch.xpack.ml.integration.ClassificationIT
474465
method: testWithDatastreams
475466
issue: https://github.com/elastic/elasticsearch/issues/129457
476-
- class: org.elasticsearch.xpack.security.PermissionsIT
477-
method: testCanManageIndexWithNoPermissions
478-
issue: https://github.com/elastic/elasticsearch/issues/129471
479-
- class: org.elasticsearch.xpack.security.PermissionsIT
480-
method: testCanManageIndexAndPolicyDifferentUsers
481-
issue: https://github.com/elastic/elasticsearch/issues/129479
482-
- class: org.elasticsearch.xpack.security.PermissionsIT
483-
method: testCanViewExplainOnUnmanagedIndex
484-
issue: https://github.com/elastic/elasticsearch/issues/129480
485467
- class: org.elasticsearch.xpack.profiling.action.GetStatusActionIT
486468
method: testWaitsUntilResourcesAreCreated
487469
issue: https://github.com/elastic/elasticsearch/issues/129486
@@ -500,21 +482,12 @@ tests:
500482
- class: org.elasticsearch.search.query.VectorIT
501483
method: testFilteredQueryStrategy
502484
issue: https://github.com/elastic/elasticsearch/issues/129517
503-
- class: org.elasticsearch.snapshots.SnapshotShutdownIT
504-
method: testSnapshotShutdownProgressTracker
505-
issue: https://github.com/elastic/elasticsearch/issues/129752
506485
- class: org.elasticsearch.xpack.security.SecurityRolesMultiProjectIT
507486
method: testUpdatingFileBasedRoleAffectsAllProjects
508487
issue: https://github.com/elastic/elasticsearch/issues/129775
509488
- class: org.elasticsearch.qa.verify_version_constants.VerifyVersionConstantsIT
510489
method: testLuceneVersionConstant
511490
issue: https://github.com/elastic/elasticsearch/issues/125638
512-
- class: org.elasticsearch.index.store.FsDirectoryFactoryTests
513-
method: testPreload
514-
issue: https://github.com/elastic/elasticsearch/issues/129852
515-
- class: org.elasticsearch.xpack.test.rest.XPackRestIT
516-
method: test {p0=esql/60_usage/Basic ESQL usage output (telemetry) non-snapshot version}
517-
issue: https://github.com/elastic/elasticsearch/issues/129888
518491
- class: org.elasticsearch.gradle.internal.InternalDistributionBwcSetupPluginFuncTest
519492
method: "builds distribution from branches via archives extractedAssemble [bwcDistVersion: 8.2.1, bwcProject: bugfix, expectedAssembleTaskName:
520493
extractedAssemble, #2]"
@@ -578,9 +551,6 @@ tests:
578551
- class: org.elasticsearch.xpack.esql.qa.single_node.GenerativeIT
579552
method: test
580553
issue: https://github.com/elastic/elasticsearch/issues/130067
581-
- class: org.elasticsearch.index.codec.vectors.cluster.HierarchicalKMeansTests
582-
method: testHKmeans
583-
issue: https://github.com/elastic/elasticsearch/issues/130497
584554
- class: org.elasticsearch.backwards.MixedClusterClientYamlTestSuiteIT
585555
method: test {p0=search.vectors/40_knn_search/Dimensions are dynamically set}
586556
issue: https://github.com/elastic/elasticsearch/issues/130626
@@ -593,6 +563,9 @@ tests:
593563
- class: org.elasticsearch.xpack.esql.qa.single_node.EsqlSpecIT
594564
method: test {lookup-join.MvJoinKeyFromRow ASYNC}
595565
issue: https://github.com/elastic/elasticsearch/issues/130642
566+
- class: org.elasticsearch.index.engine.ThreadPoolMergeExecutorServiceDiskSpaceTests
567+
method: testUnavailableBudgetBlocksNewMergeTasksFromStartingExecution
568+
issue: https://github.com/elastic/elasticsearch/issues/130205
596569

597570
# Examples:
598571
#

rest-api-spec/src/main/resources/rest-api-spec/api/cluster.put_component_template.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@
3333
"description":"Whether the index template should only be added if new or can also replace an existing one",
3434
"default":false
3535
},
36-
"timeout":{
37-
"type":"time",
38-
"description":"Explicit operation timeout"
36+
"cause": {
37+
"type": "string",
38+
"description": "User defined reason for create the component template",
39+
"default": "api"
3940
},
4041
"master_timeout":{
4142
"type":"time",

server/src/main/java/org/elasticsearch/index/codec/vectors/cluster/KMeansLocal.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,10 @@ private void cluster(FloatVectorValues vectors, KMeansIntermediate kMeansInterme
329329
float[][] centroids = kMeansIntermediate.centroids();
330330
int k = centroids.length;
331331
int n = vectors.size();
332+
int[] assignments = kMeansIntermediate.assignments();
332333

333-
if (k == 1 || k >= n) {
334+
if (k == 1) {
335+
Arrays.fill(assignments, 0);
334336
return;
335337
}
336338
IntToIntFunction translateOrd = i -> i;
@@ -339,7 +341,7 @@ private void cluster(FloatVectorValues vectors, KMeansIntermediate kMeansInterme
339341
sampledVectors = SampleReader.createSampleReader(vectors, sampleSize, 42L);
340342
translateOrd = sampledVectors::ordToDoc;
341343
}
342-
int[] assignments = kMeansIntermediate.assignments();
344+
343345
assert assignments.length == n;
344346
float[][] nextCentroids = new float[centroids.length][vectors.dimension()];
345347
for (int i = 0; i < maxIterations; i++) {
@@ -349,7 +351,7 @@ private void cluster(FloatVectorValues vectors, KMeansIntermediate kMeansInterme
349351
}
350352
}
351353
// If we were sampled, do a once over the full set of vectors to finalize the centroids
352-
if (sampleSize < n) {
354+
if (sampleSize < n || maxIterations == 0) {
353355
// No ordinal translation needed here, we are using the full set of vectors
354356
stepLloyd(vectors, i -> i, centroids, nextCentroids, assignments, neighborhoods);
355357
}

server/src/test/java/org/elasticsearch/index/codec/vectors/cluster/HierarchicalKMeansTests.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ public class HierarchicalKMeansTests extends ESTestCase {
1919

2020
public void testHKmeans() throws IOException {
2121
int nClusters = random().nextInt(1, 10);
22-
int nVectors = random().nextInt(nClusters * 100, nClusters * 200);
22+
int nVectors = random().nextInt(1, nClusters * 200);
2323
int dims = random().nextInt(2, 20);
24-
int sampleSize = random().nextInt(100, nVectors + 1);
25-
int maxIterations = random().nextInt(0, 100);
24+
int sampleSize = random().nextInt(Math.min(nVectors, 100), nVectors + 1);
25+
int maxIterations = random().nextInt(1, 100);
2626
int clustersPerNeighborhood = random().nextInt(2, 512);
2727
float soarLambda = random().nextFloat(0.5f, 1.5f);
2828
FloatVectorValues vectors = generateData(nVectors, dims, nClusters);
@@ -36,14 +36,16 @@ public void testHKmeans() throws IOException {
3636
int[] assignments = result.assignments();
3737
int[] soarAssignments = result.soarAssignments();
3838

39-
assertEquals(nClusters, centroids.length, 6);
39+
assertEquals(Math.min(nClusters, nVectors), centroids.length, 8);
4040
assertEquals(nVectors, assignments.length);
41-
if (centroids.length > 1 && clustersPerNeighborhood > 0) {
41+
if (centroids.length > 1 && centroids.length < nVectors) {
4242
assertEquals(nVectors, soarAssignments.length);
4343
// verify no duplicates exist
4444
for (int i = 0; i < assignments.length; i++) {
4545
assert assignments[i] != soarAssignments[i];
4646
}
47+
} else {
48+
assertEquals(0, soarAssignments.length);
4749
}
4850
}
4951

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/KnnFunctionIT.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
package org.elasticsearch.xpack.esql.plugin;
99

1010
import org.elasticsearch.action.index.IndexRequestBuilder;
11+
import org.elasticsearch.client.internal.IndicesAdminClient;
1112
import org.elasticsearch.cluster.metadata.IndexMetadata;
1213
import org.elasticsearch.common.settings.Settings;
14+
import org.elasticsearch.index.IndexSettings;
1315
import org.elasticsearch.xcontent.XContentBuilder;
1416
import org.elasticsearch.xcontent.XContentFactory;
1517
import org.elasticsearch.xpack.esql.EsqlTestUtils;
18+
import org.elasticsearch.xpack.esql.VerificationException;
1619
import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase;
1720
import org.elasticsearch.xpack.esql.action.EsqlCapabilities;
1821
import org.junit.Before;
@@ -25,7 +28,9 @@
2528
import java.util.Locale;
2629
import java.util.Map;
2730

31+
import static org.elasticsearch.index.IndexMode.LOOKUP;
2832
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
33+
import static org.hamcrest.CoreMatchers.containsString;
2934

3035
public class KnnFunctionIT extends AbstractEsqlIntegTestCase {
3136

@@ -109,6 +114,26 @@ public void testKnnNonPushedDown() {
109114
}
110115
}
111116

117+
public void testKnnWithLookupJoin() {
118+
float[] queryVector = new float[numDims];
119+
Arrays.fill(queryVector, 1.0f);
120+
121+
var query = String.format(Locale.ROOT, """
122+
FROM test
123+
| LOOKUP JOIN test_lookup ON id
124+
| WHERE KNN(lookup_vector, %s, 5) OR id > 10
125+
""", Arrays.toString(queryVector));
126+
127+
var error = expectThrows(VerificationException.class, () -> run(query));
128+
assertThat(
129+
error.getMessage(),
130+
containsString(
131+
"line 3:13: [KNN] function cannot operate on [lookup_vector], supplied by an index [test_lookup] in non-STANDARD "
132+
+ "mode [lookup]"
133+
)
134+
);
135+
}
136+
112137
@Before
113138
public void setup() throws IOException {
114139
assumeTrue("Needs KNN support", EsqlCapabilities.Cap.KNN_FUNCTION_V2.isEnabled());
@@ -152,5 +177,31 @@ public void setup() throws IOException {
152177
}
153178

154179
indexRandom(true, docs);
180+
181+
createAndPopulateLookupIndex(client, "test_lookup");
182+
}
183+
184+
private void createAndPopulateLookupIndex(IndicesAdminClient client, String lookupIndexName) throws IOException {
185+
XContentBuilder mapping = XContentFactory.jsonBuilder()
186+
.startObject()
187+
.startObject("properties")
188+
.startObject("id")
189+
.field("type", "integer")
190+
.endObject()
191+
.startObject("lookup_vector")
192+
.field("type", "dense_vector")
193+
.field("similarity", "l2_norm")
194+
.endObject()
195+
.endObject()
196+
.endObject();
197+
198+
Settings.Builder settingsBuilder = Settings.builder()
199+
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0)
200+
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
201+
.put(IndexSettings.MODE.getKey(), LOOKUP.getName());
202+
203+
var createRequest = client.prepareCreate(lookupIndexName).setMapping(mapping).setSettings(settingsBuilder.build());
204+
assertAcked(createRequest);
205+
155206
}
156207
}

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchFunctionIT.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
import org.elasticsearch.ElasticsearchException;
1111
import org.elasticsearch.action.index.IndexRequest;
1212
import org.elasticsearch.action.support.WriteRequest;
13+
import org.elasticsearch.client.internal.IndicesAdminClient;
1314
import org.elasticsearch.common.settings.Settings;
1415
import org.elasticsearch.xpack.esql.VerificationException;
1516
import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase;
1617
import org.hamcrest.Matchers;
1718
import org.junit.Before;
1819

1920
import java.util.List;
21+
import java.util.function.Consumer;
2022

2123
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
2224
import static org.elasticsearch.xpack.esql.EsqlTestUtils.getValuesList;
@@ -27,7 +29,7 @@ public class MatchFunctionIT extends AbstractEsqlIntegTestCase {
2729

2830
@Before
2931
public void setupIndex() {
30-
createAndPopulateIndex();
32+
createAndPopulateIndex(this::ensureYellow);
3133
}
3234

3335
public void testSimpleWhereMatch() {
@@ -294,13 +296,30 @@ public void testMatchWithinEval() {
294296
assertThat(error.getMessage(), containsString("[MATCH] function is only supported in WHERE and STATS commands"));
295297
}
296298

297-
private void createAndPopulateIndex() {
299+
public void testMatchWithLookupJoin() {
300+
var query = """
301+
FROM test
302+
| LOOKUP JOIN test_lookup ON id
303+
| WHERE id > 0 AND MATCH(lookup_content, "fox")
304+
""";
305+
306+
var error = expectThrows(VerificationException.class, () -> run(query));
307+
assertThat(
308+
error.getMessage(),
309+
containsString(
310+
"line 3:26: [MATCH] function cannot operate on [lookup_content], supplied by an index [test_lookup] "
311+
+ "in non-STANDARD mode [lookup]"
312+
)
313+
);
314+
}
315+
316+
static void createAndPopulateIndex(Consumer<String[]> ensureYellow) {
298317
var indexName = "test";
299318
var client = client().admin().indices();
300-
var CreateRequest = client.prepareCreate(indexName)
319+
var createRequest = client.prepareCreate(indexName)
301320
.setSettings(Settings.builder().put("index.number_of_shards", 1))
302321
.setMapping("id", "type=integer", "content", "type=text");
303-
assertAcked(CreateRequest);
322+
assertAcked(createRequest);
304323
client().prepareBulk()
305324
.add(new IndexRequest(indexName).id("1").source("id", 1, "content", "This is a brown fox"))
306325
.add(new IndexRequest(indexName).id("2").source("id", 2, "content", "This is a brown dog"))
@@ -310,6 +329,17 @@ private void createAndPopulateIndex() {
310329
.add(new IndexRequest(indexName).id("6").source("id", 6, "content", "The quick brown fox jumps over the lazy dog"))
311330
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
312331
.get();
313-
ensureYellow(indexName);
332+
333+
var lookupIndexName = "test_lookup";
334+
createAndPopulateLookupIndex(client, lookupIndexName);
335+
336+
ensureYellow.accept(new String[] { indexName, lookupIndexName });
337+
}
338+
339+
static void createAndPopulateLookupIndex(IndicesAdminClient client, String lookupIndexName) {
340+
var createRequest = client.prepareCreate(lookupIndexName)
341+
.setSettings(Settings.builder().put("index.number_of_shards", 1).put("index.mode", "lookup"))
342+
.setMapping("id", "type=integer", "lookup_content", "type=text");
343+
assertAcked(createRequest);
314344
}
315345
}

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/MatchOperatorIT.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@
88
package org.elasticsearch.xpack.esql.plugin;
99

1010
import org.elasticsearch.ElasticsearchException;
11-
import org.elasticsearch.action.index.IndexRequest;
12-
import org.elasticsearch.action.support.WriteRequest;
13-
import org.elasticsearch.common.settings.Settings;
1411
import org.elasticsearch.index.query.QueryBuilder;
1512
import org.elasticsearch.index.query.QueryBuilders;
1613
import org.elasticsearch.xpack.esql.VerificationException;
@@ -21,7 +18,6 @@
2118

2219
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
2320
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
24-
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
2521
import static org.elasticsearch.xpack.esql.action.EsqlQueryRequest.syncEsqlQueryRequest;
2622
import static org.hamcrest.CoreMatchers.containsString;
2723

@@ -30,7 +26,7 @@ public class MatchOperatorIT extends AbstractEsqlIntegTestCase {
3026

3127
@Before
3228
public void setupIndex() {
33-
createAndPopulateIndex();
29+
MatchFunctionIT.createAndPopulateIndex(this::ensureYellow);
3430
}
3531

3632
public void testSimpleWhereMatch() {
@@ -372,22 +368,20 @@ public void testMatchWithNonTextField() {
372368
}
373369
}
374370

375-
private void createAndPopulateIndex() {
376-
var indexName = "test";
377-
var client = client().admin().indices();
378-
var CreateRequest = client.prepareCreate(indexName)
379-
.setSettings(Settings.builder().put("index.number_of_shards", 1))
380-
.setMapping("id", "type=integer", "content", "type=text");
381-
assertAcked(CreateRequest);
382-
client().prepareBulk()
383-
.add(new IndexRequest(indexName).id("1").source("id", 1, "content", "This is a brown fox"))
384-
.add(new IndexRequest(indexName).id("2").source("id", 2, "content", "This is a brown dog"))
385-
.add(new IndexRequest(indexName).id("3").source("id", 3, "content", "This dog is really brown"))
386-
.add(new IndexRequest(indexName).id("4").source("id", 4, "content", "The dog is brown but this document is very very long"))
387-
.add(new IndexRequest(indexName).id("5").source("id", 5, "content", "There is also a white cat"))
388-
.add(new IndexRequest(indexName).id("6").source("id", 6, "content", "The quick brown fox jumps over the lazy dog"))
389-
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
390-
.get();
391-
ensureYellow(indexName);
371+
public void testMatchOperatorWithLookupJoin() {
372+
var query = """
373+
FROM test
374+
| LOOKUP JOIN test_lookup ON id
375+
| WHERE id > 0 AND lookup_content : "fox"
376+
""";
377+
378+
var error = expectThrows(VerificationException.class, () -> run(query));
379+
assertThat(
380+
error.getMessage(),
381+
containsString(
382+
"line 3:20: [:] operator cannot operate on [lookup_content], supplied by an index [test_lookup] "
383+
+ "in non-STANDARD mode [lookup]"
384+
)
385+
);
392386
}
393387
}

0 commit comments

Comments
 (0)