Ver código fonte

Limit several determinization limits for automata (#97489)

Determinization of automata can be an expensive operation, which is why Lucenes
MinimizationOperations allows to limit the amount of work allowed in this step.
The default limit should be Operations.DEFAULT_DETERMINIZE_WORK_LIMIT, but we
use Integer.MAX in several places. Instead, we can limit this to even 0 in many
places where by the construction of the automaton it is clear that it is already
determinized.
This changes this limit to 0 where possible and adds tests and assertions to
make sure the constructed automata are deterministic already, also simplifying
some internal API along the way.

Relates to #96572
Christoph Büscher 2 anos atrás
pai
commit
f61d08e907
16 arquivos alterados com 176 adições e 46 exclusões
  1. 18 12
      server/src/main/java/org/elasticsearch/common/lucene/search/AutomatonQueries.java
  2. 2 2
      server/src/main/java/org/elasticsearch/index/mapper/IpPrefixAutomatonUtil.java
  3. 6 5
      server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java
  4. 2 2
      server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java
  5. 1 1
      server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java
  6. 2 1
      server/src/main/java/org/elasticsearch/index/mapper/flattened/FlattenedFieldMapper.java
  7. 10 6
      server/src/main/java/org/elasticsearch/indices/SystemIndices.java
  8. 1 1
      server/src/main/java/org/elasticsearch/search/runtime/StringScriptFieldWildcardQuery.java
  9. 88 0
      server/src/test/java/org/elasticsearch/common/lucene/search/AutomatonQueriesTests.java
  10. 0 2
      server/src/test/java/org/elasticsearch/index/mapper/IpPrefixAutomatonUtilTests.java
  11. 40 0
      server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldTypeTests.java
  12. 0 5
      x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/action/MultiShardTermsEnumTests.java
  13. 3 3
      x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionEncoder.java
  14. 1 1
      x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionFieldWildcardQuery.java
  15. 1 1
      x-pack/plugin/wildcard/src/main/java/org/elasticsearch/xpack/wildcard/mapper/WildcardFieldMapper.java
  16. 1 4
      x-pack/plugin/wildcard/src/test/java/org/elasticsearch/xpack/wildcard/mapper/WildcardFieldMapperTests.java

+ 18 - 12
server/src/main/java/org/elasticsearch/common/lucene/search/AutomatonQueries.java

@@ -30,12 +30,15 @@ public class AutomatonQueries {
         List<Automaton> list = new ArrayList<>();
         Iterator<Integer> iter = s.codePoints().iterator();
         while (iter.hasNext()) {
-            list.add(toCaseInsensitiveChar(iter.next(), Integer.MAX_VALUE));
+            list.add(toCaseInsensitiveChar(iter.next()));
         }
         list.add(Automata.makeAnyString());
 
         Automaton a = Operations.concatenate(list);
-        a = MinimizationOperations.minimize(a, Integer.MAX_VALUE);
+        // since all elements in the list should be deterministic already, the concatenation also is, so no need to determinized
+        assert a.isDeterministic();
+        a = MinimizationOperations.minimize(a, 0);
+        assert a.isDeterministic();
         return a;
     }
 
@@ -52,7 +55,7 @@ public class AutomatonQueries {
 
     /** Build an automaton matching a wildcard pattern, ASCII case insensitive. */
     public static AutomatonQuery caseInsensitiveWildcardQuery(Term wildcardquery) {
-        return new AutomatonQuery(wildcardquery, toCaseInsensitiveWildcardAutomaton(wildcardquery, Integer.MAX_VALUE));
+        return new AutomatonQuery(wildcardquery, toCaseInsensitiveWildcardAutomaton(wildcardquery));
     }
 
     /** String equality with support for wildcards */
@@ -68,7 +71,7 @@ public class AutomatonQueries {
      * Convert Lucene wildcard syntax into an automaton.
      */
     @SuppressWarnings("fallthrough")
-    public static Automaton toCaseInsensitiveWildcardAutomaton(Term wildcardquery, int maxDeterminizedStates) {
+    public static Automaton toCaseInsensitiveWildcardAutomaton(Term wildcardquery) {
         List<Automaton> automata = new ArrayList<>();
 
         String wildcardText = wildcardquery.text();
@@ -92,7 +95,7 @@ public class AutomatonQueries {
                         break;
                     } // else fallthru, lenient parsing with a trailing \
                 default:
-                    automata.add(toCaseInsensitiveChar(c, maxDeterminizedStates));
+                    automata.add(toCaseInsensitiveChar(c));
             }
             i += length;
         }
@@ -101,23 +104,24 @@ public class AutomatonQueries {
     }
 
     protected static Automaton toCaseInsensitiveString(BytesRef br) {
-        return toCaseInsensitiveString(br.utf8ToString(), Integer.MAX_VALUE);
+        return toCaseInsensitiveString(br.utf8ToString());
     }
 
-    public static Automaton toCaseInsensitiveString(String s, int maxDeterminizedStates) {
+    public static Automaton toCaseInsensitiveString(String s) {
         List<Automaton> list = new ArrayList<>();
         Iterator<Integer> iter = s.codePoints().iterator();
         while (iter.hasNext()) {
-            list.add(toCaseInsensitiveChar(iter.next(), maxDeterminizedStates));
+            list.add(toCaseInsensitiveChar(iter.next()));
         }
 
         Automaton a = Operations.concatenate(list);
-        a = MinimizationOperations.minimize(a, maxDeterminizedStates);
+        // concatenating deterministic automata should result in a deterministic automaton. No need to determinize here.
+        assert a.isDeterministic();
+        a = MinimizationOperations.minimize(a, 0);
         return a;
-
     }
 
-    public static Automaton toCaseInsensitiveChar(int codepoint, int maxDeterminizedStates) {
+    public static Automaton toCaseInsensitiveChar(int codepoint) {
         Automaton case1 = Automata.makeChar(codepoint);
         // For now we only work with ASCII characters
         if (codepoint > 128) {
@@ -127,7 +131,9 @@ public class AutomatonQueries {
         Automaton result;
         if (altCase != codepoint) {
             result = Operations.union(case1, Automata.makeChar(altCase));
-            result = MinimizationOperations.minimize(result, maxDeterminizedStates);
+            // this automaton should always be deterministic, no need to determinize
+            result = MinimizationOperations.minimize(result, 0);
+            assert result.isDeterministic();
         } else {
             result = case1;
         }

+ 2 - 2
server/src/main/java/org/elasticsearch/index/mapper/IpPrefixAutomatonUtil.java

@@ -75,8 +75,8 @@ public class IpPrefixAutomatonUtil {
         } else {
             result = Automata.makeAnyBinary();
         }
-        result = MinimizationOperations.minimize(result, Integer.MAX_VALUE);
-        return new CompiledAutomaton(result, null, false, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT, true);
+        result = MinimizationOperations.minimize(result, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
+        return new CompiledAutomaton(result, null, false, 0, true);
     }
 
     private static Automaton getIpv6Automaton(String ipPrefix) {

+ 6 - 5
server/src/main/java/org/elasticsearch/index/mapper/KeywordFieldMapper.java

@@ -530,7 +530,6 @@ public final class KeywordFieldMapper extends FieldMapper {
 
         @Override
         public TermsEnum getTerms(IndexReader reader, String prefix, boolean caseInsensitive, String searchAfter) throws IOException {
-
             Terms terms = null;
             if (isIndexed()) {
                 terms = MultiTerms.getTerms(reader, name());
@@ -541,11 +540,13 @@ public final class KeywordFieldMapper extends FieldMapper {
                 // Field does not exist on this shard.
                 return null;
             }
-            Automaton a = caseInsensitive ? AutomatonQueries.caseInsensitivePrefix(prefix) : Automata.makeString(prefix);
-            a = Operations.concatenate(a, Automata.makeAnyString());
-            a = MinimizationOperations.minimize(a, Integer.MAX_VALUE);
+            Automaton a = caseInsensitive
+                ? AutomatonQueries.caseInsensitivePrefix(prefix)
+                : Operations.concatenate(Automata.makeString(prefix), Automata.makeAnyString());
+            assert a.isDeterministic();
+            a = MinimizationOperations.minimize(a, 0);
 
-            CompiledAutomaton automaton = new CompiledAutomaton(a);
+            CompiledAutomaton automaton = new CompiledAutomaton(a, true, true);
 
             BytesRef searchBytes = searchAfter == null ? null : new BytesRef(searchAfter);
 

+ 2 - 2
server/src/main/java/org/elasticsearch/index/mapper/StringFieldType.java

@@ -168,10 +168,10 @@ public abstract class StringFieldType extends TermBasedFieldType {
         }
         if (caseInsensitive) {
             return method == null
-                ? new AutomatonQuery(term, toCaseInsensitiveWildcardAutomaton(term, Integer.MAX_VALUE))
+                ? new AutomatonQuery(term, toCaseInsensitiveWildcardAutomaton(term))
                 : new AutomatonQuery(
                     term,
-                    toCaseInsensitiveWildcardAutomaton(term, Integer.MAX_VALUE),
+                    toCaseInsensitiveWildcardAutomaton(term),
                     Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
                     false,
                     method

+ 1 - 1
server/src/main/java/org/elasticsearch/index/mapper/TextFieldMapper.java

@@ -610,7 +610,7 @@ public class TextFieldMapper extends FieldMapper {
             }
             List<Automaton> automata = new ArrayList<>();
             if (caseInsensitive) {
-                automata.add(AutomatonQueries.toCaseInsensitiveString(value, Integer.MAX_VALUE));
+                automata.add(AutomatonQueries.toCaseInsensitiveString(value));
             } else {
                 automata.add(Automata.makeString(value));
             }

+ 2 - 1
server/src/main/java/org/elasticsearch/index/mapper/flattened/FlattenedFieldMapper.java

@@ -385,7 +385,8 @@ public final class FlattenedFieldMapper extends FieldMapper {
                 a = Operations.concatenate(a, Automata.makeString(prefix));
                 a = Operations.concatenate(a, Automata.makeAnyString());
             }
-            a = MinimizationOperations.minimize(a, Integer.MAX_VALUE);
+            assert a.isDeterministic();
+            a = MinimizationOperations.minimize(a, 0);
 
             CompiledAutomaton automaton = new CompiledAutomaton(a);
             if (searchAfter != null) {

+ 10 - 6
server/src/main/java/org/elasticsearch/indices/SystemIndices.java

@@ -177,7 +177,7 @@ public class SystemIndices {
         this.executorSelector = new ExecutorSelector(this);
         this.systemNameAutomaton = MinimizationOperations.minimize(
             Operations.union(List.of(systemIndexAutomata, systemDataStreamIndicesAutomata, buildDataStreamAutomaton(featureDescriptors))),
-            Integer.MAX_VALUE
+            Operations.DEFAULT_DETERMINIZE_WORK_LIMIT
         );
         this.systemNameRunAutomaton = new CharacterRunAutomaton(systemNameAutomaton);
     }
@@ -261,7 +261,9 @@ public class SystemIndices {
             .collect(
                 Collectors.toUnmodifiableMap(
                     Entry::getKey,
-                    entry -> new CharacterRunAutomaton(MinimizationOperations.minimize(entry.getValue(), Integer.MAX_VALUE))
+                    entry -> new CharacterRunAutomaton(
+                        MinimizationOperations.minimize(entry.getValue(), Operations.DEFAULT_DETERMINIZE_WORK_LIMIT)
+                    )
                 )
             );
     }
@@ -421,7 +423,7 @@ public class SystemIndices {
             .stream()
             .map(SystemIndices::featureToIndexAutomaton)
             .reduce(Operations::union);
-        return MinimizationOperations.minimize(automaton.orElse(EMPTY), Integer.MAX_VALUE);
+        return MinimizationOperations.minimize(automaton.orElse(EMPTY), Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
     }
 
     private static CharacterRunAutomaton buildNetNewIndexCharacterRunAutomaton(Map<String, Feature> featureDescriptors) {
@@ -432,7 +434,9 @@ public class SystemIndices {
             .filter(SystemIndexDescriptor::isNetNew)
             .map(descriptor -> SystemIndexDescriptor.buildAutomaton(descriptor.getIndexPattern(), descriptor.getAliasName()))
             .reduce(Operations::union);
-        return new CharacterRunAutomaton(MinimizationOperations.minimize(automaton.orElse(EMPTY), Integer.MAX_VALUE));
+        return new CharacterRunAutomaton(
+            MinimizationOperations.minimize(automaton.orElse(EMPTY), Operations.DEFAULT_DETERMINIZE_WORK_LIMIT)
+        );
     }
 
     private static Automaton featureToIndexAutomaton(Feature feature) {
@@ -452,7 +456,7 @@ public class SystemIndices {
             .map(dsName -> SystemIndexDescriptor.buildAutomaton(dsName, null))
             .reduce(Operations::union);
 
-        return automaton.isPresent() ? MinimizationOperations.minimize(automaton.get(), Integer.MAX_VALUE) : EMPTY;
+        return automaton.isPresent() ? MinimizationOperations.minimize(automaton.get(), Operations.DEFAULT_DETERMINIZE_WORK_LIMIT) : EMPTY;
     }
 
     private static Predicate<String> buildDataStreamNamePredicate(Map<String, Feature> featureDescriptors) {
@@ -465,7 +469,7 @@ public class SystemIndices {
             .stream()
             .map(SystemIndices::featureToDataStreamBackingIndicesAutomaton)
             .reduce(Operations::union);
-        return MinimizationOperations.minimize(automaton.orElse(EMPTY), Integer.MAX_VALUE);
+        return MinimizationOperations.minimize(automaton.orElse(EMPTY), Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
     }
 
     private static Automaton featureToDataStreamBackingIndicesAutomaton(Feature feature) {

+ 1 - 1
server/src/main/java/org/elasticsearch/search/runtime/StringScriptFieldWildcardQuery.java

@@ -41,7 +41,7 @@ public class StringScriptFieldWildcardQuery extends AbstractStringScriptFieldAut
 
     private static Automaton buildAutomaton(Term term, boolean caseInsensitive) {
         if (caseInsensitive) {
-            return AutomatonQueries.toCaseInsensitiveWildcardAutomaton(term, Integer.MAX_VALUE);
+            return AutomatonQueries.toCaseInsensitiveWildcardAutomaton(term);
         }
         return WildcardQuery.toAutomaton(term);
     }

+ 88 - 0
server/src/test/java/org/elasticsearch/common/lucene/search/AutomatonQueriesTests.java

@@ -0,0 +1,88 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.common.lucene.search;
+
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.automaton.Automaton;
+import org.apache.lucene.util.automaton.ByteRunAutomaton;
+import org.elasticsearch.test.ESTestCase;
+
+import java.util.Locale;
+
+public class AutomatonQueriesTests extends ESTestCase {
+
+    public void testToCaseInsensitiveChar() {
+        int codepoint = randomBoolean() ? randomInt(128) : randomUnicodeOfLength(1).codePointAt(0);
+        Automaton automaton = AutomatonQueries.toCaseInsensitiveChar(codepoint);
+        assertTrue(automaton.isDeterministic());
+        ByteRunAutomaton runAutomaton = new ByteRunAutomaton(automaton);
+        BytesRef br = new BytesRef(new String(Character.toChars(codepoint)));
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+        // only codepoints below 128 are converted to a case-insensitive automaton, so only test that for those cases
+        if (codepoint <= 128) {
+            int altCase = Character.isLowerCase(codepoint) ? Character.toUpperCase(codepoint) : Character.toLowerCase(codepoint);
+            br = new BytesRef(new String(Character.toChars(altCase)));
+            assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+        }
+    }
+
+    public void testToCaseInsensitiveString() {
+        String s = randomAlphaOfLengthBetween(10, 100);
+        Automaton automaton = AutomatonQueries.toCaseInsensitiveString(s);
+        assertTrue(automaton.isDeterministic());
+        ByteRunAutomaton runAutomaton = new ByteRunAutomaton(automaton);
+        BytesRef br = new BytesRef(s);
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+        br = new BytesRef(randomBoolean() ? s.toLowerCase(Locale.ROOT) : s.toUpperCase(Locale.ROOT));
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+
+        // we cannot really upper/lowercase any random unicode string, for details
+        // see restrictions in AutomatonQueries.toCaseInsensitiveChar, but we can
+        // at least check the original string is accepted
+        s = randomRealisticUnicodeOfLengthBetween(10, 100);
+        automaton = AutomatonQueries.toCaseInsensitiveString(s);
+        runAutomaton = new ByteRunAutomaton(automaton);
+        br = new BytesRef(s);
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+
+        s = randomUnicodeOfLengthBetween(10, 100);
+        automaton = AutomatonQueries.toCaseInsensitiveString(s);
+        runAutomaton = new ByteRunAutomaton(automaton);
+        br = new BytesRef(s);
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+    }
+
+    public void testToCaseInsensitivePrefix() {
+        String s = randomAlphaOfLengthBetween(10, 100);
+        Automaton automaton = AutomatonQueries.caseInsensitivePrefix(s);
+        assertTrue(automaton.isDeterministic());
+        ByteRunAutomaton runAutomaton = new ByteRunAutomaton(automaton);
+        BytesRef br = new BytesRef(s + randomRealisticUnicodeOfLengthBetween(10, 20));
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+        br = new BytesRef(
+            (randomBoolean() ? s.toLowerCase(Locale.ROOT) : s.toUpperCase(Locale.ROOT)) + randomRealisticUnicodeOfLengthBetween(10, 20)
+        );
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+
+        // We cannot uppercase or lowercase any random unicode string.
+        // For details see restrictions in AutomatonQueries.toCaseInsensitiveChar.
+        // However, we can at least check the original string is accepted here.
+        s = randomRealisticUnicodeOfLengthBetween(10, 100);
+        automaton = AutomatonQueries.caseInsensitivePrefix(s);
+        runAutomaton = new ByteRunAutomaton(automaton);
+        br = new BytesRef(s + randomRealisticUnicodeOfLengthBetween(10, 20));
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+
+        s = randomUnicodeOfLengthBetween(10, 100);
+        automaton = AutomatonQueries.caseInsensitivePrefix(s);
+        runAutomaton = new ByteRunAutomaton(automaton);
+        br = new BytesRef(s + randomRealisticUnicodeOfLengthBetween(10, 20));
+        assertTrue(runAutomaton.run(br.bytes, br.offset, br.length));
+    }
+}

+ 0 - 2
server/src/test/java/org/elasticsearch/index/mapper/IpPrefixAutomatonUtilTests.java

@@ -12,7 +12,6 @@ import org.apache.commons.codec.binary.Hex;
 import org.apache.lucene.document.InetAddressPoint;
 import org.apache.lucene.util.automaton.Automaton;
 import org.apache.lucene.util.automaton.CompiledAutomaton;
-import org.apache.lucene.util.automaton.MinimizationOperations;
 import org.apache.lucene.util.automaton.Operations;
 import org.elasticsearch.common.network.NetworkAddress;
 import org.elasticsearch.test.ESTestCase;
@@ -224,7 +223,6 @@ public class IpPrefixAutomatonUtilTests extends ESTestCase {
     }
 
     private static CompiledAutomaton compileAutomaton(Automaton automaton) {
-        automaton = MinimizationOperations.minimize(automaton, Integer.MAX_VALUE);
         CompiledAutomaton compiledAutomaton = new CompiledAutomaton(
             automaton,
             null,

+ 40 - 0
server/src/test/java/org/elasticsearch/index/mapper/KeywordFieldTypeTests.java

@@ -16,15 +16,23 @@ import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.core.WhitespaceTokenizer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.SortedSetDocValuesField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.FieldExistsQuery;
 import org.apache.lucene.search.FuzzyQuery;
 import org.apache.lucene.search.RegexpQuery;
 import org.apache.lucene.search.TermInSetQuery;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.tests.index.RandomIndexWriter;
 import org.apache.lucene.util.BytesRef;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.common.lucene.BytesRefs;
@@ -245,6 +253,38 @@ public class KeywordFieldTypeTests extends FieldTypeTestCase {
         assertEquals(List.of("NULL"), fetchSourceValue(nullValueMapper, null));
     }
 
+    public void testGetTerms() throws IOException {
+        MappedFieldType ft = new KeywordFieldType("field");
+        try (Directory dir = newDirectory()) {
+            RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
+            for (int i = 0; i < 20; i++) {
+                Document doc = new Document();
+                doc.add(new StringField("field", "prefix-" + "x".repeat(i), Field.Store.NO));
+                writer.addDocument(doc);
+            }
+            IndexReader reader = writer.getReader();
+            writer.close();
+
+            int from = randomIntBetween(1, 20);
+            TermsEnum terms = ft.getTerms(reader, "prefix-" + "x".repeat(from), randomBoolean(), null);
+            int numTerms = 0;
+            while (terms.next() != null) {
+                numTerms++;
+            }
+            assertEquals(20 - from, numTerms);
+
+            terms = ft.getTerms(reader, "prefix-", randomBoolean(), "prefix-" + "x".repeat(from - 1));
+            numTerms = 0;
+            while (terms.next() != null) {
+                numTerms++;
+            }
+            assertEquals(20 - from, numTerms);
+
+            terms = ft.getTerms(reader, "prefix-" + "x".repeat(IndexWriter.MAX_TERM_LENGTH), randomBoolean(), null);
+            reader.close();
+        }
+    }
+
     private static IndexAnalyzers createIndexAnalyzers() {
         return IndexAnalyzers.of(
             Map.of("default", new NamedAnalyzer("default", AnalyzerScope.INDEX, new StandardAnalyzer())),

+ 0 - 5
x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/termsenum/action/MultiShardTermsEnumTests.java

@@ -19,11 +19,8 @@ import org.apache.lucene.store.ByteBuffersDirectory;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.tests.analysis.MockAnalyzer;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.automaton.Automata;
 import org.apache.lucene.util.automaton.Automaton;
 import org.apache.lucene.util.automaton.CompiledAutomaton;
-import org.apache.lucene.util.automaton.MinimizationOperations;
-import org.apache.lucene.util.automaton.Operations;
 import org.elasticsearch.common.lucene.search.AutomatonQueries;
 import org.elasticsearch.core.IOUtils;
 import org.elasticsearch.test.ESTestCase;
@@ -70,8 +67,6 @@ public class MultiShardTermsEnumTests extends ESTestCase {
             for (int q = 0; q < numSearches; q++) {
                 String searchPrefix = randomAlphaOfLengthBetween(0, 3).toLowerCase(Locale.ROOT);
                 Automaton a = AutomatonQueries.caseInsensitivePrefix(searchPrefix);
-                a = Operations.concatenate(a, Automata.makeAnyString());
-                a = MinimizationOperations.minimize(a, Integer.MAX_VALUE);
                 CompiledAutomaton automaton = new CompiledAutomaton(a);
 
                 MultiShardTermsEnum.Builder builder = new MultiShardTermsEnum.Builder();

+ 3 - 3
x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionEncoder.java

@@ -209,13 +209,13 @@ class VersionEncoder {
         builder.setAccept(lastState, true);
         a = builder.finish();
 
-        assert a.isDeterministic();
         assert Operations.hasDeadStates(a) == false;
 
         a = Operations.concatenate(a, Automata.makeAnyBinary());
-        a = MinimizationOperations.minimize(a, Integer.MAX_VALUE);
+        assert a.isDeterministic();
+        a = MinimizationOperations.minimize(a, 0);
 
-        return new CompiledAutomaton(a, null, true, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT, true);
+        return new CompiledAutomaton(a, null, true, 0, true);
     }
 
     static class EncodedVersion {

+ 1 - 1
x-pack/plugin/mapper-version/src/main/java/org/elasticsearch/xpack/versionfield/VersionFieldWildcardQuery.java

@@ -105,7 +105,7 @@ class VersionFieldWildcardQuery extends AutomatonQuery {
                     if (caseInsensitive == false) {
                         automata.add(Automata.makeChar(c));
                     } else {
-                        automata.add(AutomatonQueries.toCaseInsensitiveChar(c, Integer.MAX_VALUE));
+                        automata.add(AutomatonQueries.toCaseInsensitiveChar(c));
                     }
             }
             i += length;

+ 1 - 1
x-pack/plugin/wildcard/src/main/java/org/elasticsearch/xpack/wildcard/mapper/WildcardFieldMapper.java

@@ -342,7 +342,7 @@ public class WildcardFieldMapper extends FieldMapper {
                 clauseCount++;
             }
             Automaton automaton = caseInsensitive
-                ? AutomatonQueries.toCaseInsensitiveWildcardAutomaton(new Term(name(), wildcardPattern), Integer.MAX_VALUE)
+                ? AutomatonQueries.toCaseInsensitiveWildcardAutomaton(new Term(name(), wildcardPattern))
                 : WildcardQuery.toAutomaton(new Term(name(), wildcardPattern));
             if (clauseCount > 0) {
                 // We can accelerate execution with the ngram query

+ 1 - 4
x-pack/plugin/wildcard/src/test/java/org/elasticsearch/xpack/wildcard/mapper/WildcardFieldMapperTests.java

@@ -678,10 +678,7 @@ public class WildcardFieldMapperTests extends MapperTestCase {
         String pattern = "A*b*B?a";
         // Case sensitivity matters when it comes to caching
         Automaton caseSensitiveAutomaton = WildcardQuery.toAutomaton(new Term("field", pattern));
-        Automaton caseInSensitiveAutomaton = AutomatonQueries.toCaseInsensitiveWildcardAutomaton(
-            new Term("field", pattern),
-            Integer.MAX_VALUE
-        );
+        Automaton caseInSensitiveAutomaton = AutomatonQueries.toCaseInsensitiveWildcardAutomaton(new Term("field", pattern));
         BinaryDvConfirmedAutomatonQuery csQ = new BinaryDvConfirmedAutomatonQuery(
             new MatchAllDocsQuery(),
             "field",