88package org .elasticsearch .xpack .esql .qa .single_node ;
99
1010import com .carrotsearch .randomizedtesting .annotations .ParametersFactory ;
11+ import com .carrotsearch .randomizedtesting .annotations .Repeat ;
1112import com .carrotsearch .randomizedtesting .annotations .ThreadLeakFilters ;
1213
1314import org .elasticsearch .client .Request ;
1415import org .apache .lucene .analysis .standard .StandardAnalyzer ;
1516import org .elasticsearch .client .Response ;
1617import org .elasticsearch .client .ResponseException ;
1718import org .elasticsearch .common .collect .Iterators ;
19+ import org .elasticsearch .core .Nullable ;
1820import org .elasticsearch .test .ListMatcher ;
1921import org .elasticsearch .test .MapMatcher ;
2022import org .elasticsearch .test .TestClustersThreadFilter ;
3436import java .util .Locale ;
3537import java .util .Map ;
3638import java .util .regex .Pattern ;
39+ import java .util .stream .Stream ;
3740
3841import static org .elasticsearch .test .ListMatcher .matchesList ;
3942import static org .elasticsearch .test .MapMatcher .assertMap ;
5154/**
5255 * Tests for pushing queries to lucene.
5356 */
57+ // @Repeat(iterations = 50)
5458@ ThreadLeakFilters (filters = TestClustersThreadFilter .class )
5559public class PushQueriesIT extends ESRestTestCase {
5660 @ ClassRule
@@ -93,22 +97,23 @@ public void testEquality() throws IOException {
9397 FROM test
9498 | WHERE test == "%value"
9599 """ ;
96- String luceneQuery = switch (type ) {
97- case AUTO , TEXT_WITH_KEYWORD -> "#test.keyword:%value -_ignored:test.keyword" ;
98- case KEYWORD , TEXT -> "test:%value" ;
99- case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> "*:*" ;
100- case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD -> "FieldExistsQuery [field=_primary_term]" ;
100+ List <String > luceneQuery = switch (type ) {
101+ case AUTO , TEXT_WITH_KEYWORD -> List .of ("#test.keyword:%value -_ignored:test.keyword" );
102+ case KEYWORD -> List .of ("test:%value" );
103+ case TEXT -> emulateLargeTextTokens (value );
104+ case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> List .of ("*:*" );
105+ case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD -> List .of ("FieldExistsQuery [field=_primary_term]" );
101106 };
102107 ComputeSignature dataNodeSignature = switch (type ) {
103108 case AUTO , CONSTANT_KEYWORD , KEYWORD , TEXT_WITH_KEYWORD -> ComputeSignature .FILTER_IN_QUERY ;
104109 case MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD , TEXT , SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD ->
105110 ComputeSignature .FILTER_IN_COMPUTE ;
106111 };
107- testPushQuery (value , esqlQuery , List . of ( luceneQuery ) , dataNodeSignature , true );
112+ testPushQuery (value , esqlQuery , luceneQuery , dataNodeSignature , true );
108113 }
109114
110115 public void testEqualityTooBigToPush () throws IOException {
111- String value = "a " .repeat (between (257 , 1000 ));
116+ String value = "v " .repeat (between (257 , 1000 ));
112117 String esqlQuery = """
113118 FROM test
114119 | WHERE test == "%value"
@@ -131,8 +136,24 @@ public void testEqualityTooBigToPush() throws IOException {
131136 * {@code NOT !=} should function just like {@code ==}.
132137 */
133138 public void testNotInequality () throws IOException {
134- // NOCOMMIT copy from previous commit
135-
139+ String value = "v" .repeat (between (0 , 256 ));
140+ String esqlQuery = """
141+ FROM test
142+ | WHERE NOT test != "%value"
143+ """ ;
144+ List <String > luceneQuery = switch (type ) {
145+ case AUTO , TEXT_WITH_KEYWORD -> List .of ("#test.keyword:%value -_ignored:test.keyword" );
146+ case KEYWORD -> List .of ("test:%value" );
147+ case TEXT -> emulateLargeTextTokens (value );
148+ case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> List .of ("*:*" );
149+ case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD -> List .of ("FieldExistsQuery [field=_primary_term]" );
150+ };
151+ ComputeSignature dataNodeSignature = switch (type ) {
152+ case AUTO , CONSTANT_KEYWORD , KEYWORD , TEXT_WITH_KEYWORD -> ComputeSignature .FILTER_IN_QUERY ;
153+ case MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD , TEXT , SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD ->
154+ ComputeSignature .FILTER_IN_COMPUTE ;
155+ };
156+ testPushQuery (value , esqlQuery , luceneQuery , dataNodeSignature , true );
136157 }
137158
138159 /**
@@ -159,36 +180,45 @@ public void testEqualityOrTooBig() throws IOException {
159180 }
160181
161182 public void testEqualityOrOther () throws IOException {
162- String value = "v" .repeat (between ( 0 , 256 ) );
183+ String value = "v" .repeat (256 );
163184 String esqlQuery = """
164185 FROM test
165186 | WHERE test == "%value" OR foo == 2
166187 """ ;
167- String luceneQuery = switch (type ) {
168- case AUTO , TEXT_WITH_KEYWORD -> "(#test.keyword:%value -_ignored:test.keyword) foo:[2 TO 2]" ;
169- case TEXT -> "#test:%value foo:[2 TO 2]" ;
170- case KEYWORD -> "test:%value foo:[2 TO 2]" ;
171- case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> "*:*" ;
172- case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD -> "FieldExistsQuery [field=_primary_term]" ;
188+ List <String > luceneQuery = switch (type ) {
189+ case AUTO , TEXT_WITH_KEYWORD -> List .of ("(#test.keyword:%value -_ignored:test.keyword) foo:[2 TO 2]" );
190+ case TEXT -> {
191+ List <String > q = emulateLargeTextTokens (value );
192+ if (q .size () > 1 ) {
193+ String s = "(" + String .join (" " , q ) + ")" ;
194+ yield List .of (s + " foo:[2 TO 2]" , "foo:[2 TO 2] " + s );
195+ }
196+ yield List .of (q .get (0 ) + " foo:[2 TO 2]" , "foo:[2 TO 2] " + q .get (0 ));
197+ }
198+ case KEYWORD -> List .of ("test:%value foo:[2 TO 2]" );
199+ case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> List .of ("*:*" );
200+ case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD -> List .of ("FieldExistsQuery [field=_primary_term]" );
173201 };
174202 ComputeSignature dataNodeSignature = switch (type ) {
175203 case AUTO , CONSTANT_KEYWORD , KEYWORD , TEXT_WITH_KEYWORD -> ComputeSignature .FILTER_IN_QUERY ;
176204 case MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD , SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD , TEXT ->
177205 ComputeSignature .FILTER_IN_COMPUTE ;
178206 };
179- testPushQuery (value , esqlQuery , List . of ( luceneQuery ) , dataNodeSignature , true );
207+ testPushQuery (value , esqlQuery , luceneQuery , dataNodeSignature , true );
180208 }
181209
182210 public void testEqualityAndOther () throws IOException {
183- String value = "v" .repeat (between ( 0 , 256 ) );
211+ String value = "v" .repeat (256 );
184212 String esqlQuery = """
185213 FROM test
186214 | WHERE test == "%value" AND foo == 1
187215 """ ;
188216 List <String > luceneQueryOptions = switch (type ) {
189217 case AUTO , TEXT_WITH_KEYWORD -> List .of ("#test.keyword:%value -_ignored:test.keyword #foo:[1 TO 1]" );
190- case TEXT -> List .of ("#foo:[1 TO 1] #test:%value" );
191218 case KEYWORD -> List .of ("#test:%value #foo:[1 TO 1]" );
219+ case TEXT -> emulateLargeTextTokens (value ).stream ()
220+ .flatMap (o -> Stream .of ("#" + o + " #foo:[1 TO 1]" , "#foo:[1 TO 1] #" + o ))
221+ .toList ();
192222 case CONSTANT_KEYWORD , MATCH_ONLY_TEXT , MATCH_ONLY_TEXT_WITH_KEYWORD -> List .of ("foo:[1 TO 1]" );
193223 case SEMANTIC_TEXT , SEMANTIC_TEXT_WITH_KEYWORD ->
194224 /*
@@ -226,7 +256,7 @@ public void testInequality() throws IOException {
226256 }
227257
228258 public void testInequalityTooBigToPush () throws IOException {
229- String value = "a " .repeat (between (257 , 1000 ));
259+ String value = "v " .repeat (between (257 , 1000 ));
230260 String esqlQuery = """
231261 FROM test
232262 | WHERE test != "%value"
@@ -246,7 +276,7 @@ public void testInequalityTooBigToPush() throws IOException {
246276 }
247277
248278 public void testCaseInsensitiveEquality () throws IOException {
249- String value = "a " .repeat (between (0 , 256 ));
279+ String value = "v " .repeat (between (0 , 256 ));
250280 String esqlQuery = """
251281 FROM test
252282 | WHERE TO_LOWER(test) == "%value"
@@ -523,11 +553,11 @@ public void setUpTextEmbeddingInferenceEndpoint() throws IOException {
523553
524554 private List <String > emulateLargeTextTokens (String value ) {
525555 // The default tokenizer splits at 255 characters
526- String first = "#test:" + "a" .repeat (StandardAnalyzer .DEFAULT_MAX_TOKEN_LENGTH );
527- if (value .length () % 255 == 0 ) {
528- return List .of (first );
556+ if (value .length () < StandardAnalyzer .DEFAULT_MAX_TOKEN_LENGTH ) {
557+ return List .of ("test:" + "v" .repeat (value .length ()));
529558 }
530- String rest = "#test:" + "a" .repeat (value .length () % 255 );
559+ String first = "#test:" + "v" .repeat (StandardAnalyzer .DEFAULT_MAX_TOKEN_LENGTH );
560+ String rest = "#test:" + "v" .repeat (value .length () % StandardAnalyzer .DEFAULT_MAX_TOKEN_LENGTH );
531561 // We don't know what order they'll show up, so either is fine.
532562 return List .of (first + " " + rest , rest + " " + first );
533563 }
0 commit comments