You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2026/04/12 16:05:31 UTC
(lucene) branch main updated: remove implicit determinization from RegexpQuery (#15939)
This is an automated email from the ASF dual-hosted git repository.
rmuir pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/lucene.git
The following commit(s) were added to refs/heads/main by this push:
new 650684e6b44 remove implicit determinization from RegexpQuery (#15939)
650684e6b44 is described below
commit 650684e6b440e0b85d3c51b3cf546c1b757975fe
Author: Robert Muir <rm...@apache.org>
AuthorDate: Sun Apr 12 12:05:25 2026 -0400
remove implicit determinization from RegexpQuery (#15939)
* remove explicit determinization from RegexpQuery
for RegexpQuery only, remove explicit determinization. If your regular
expression happens to be a DFA already, then you get a DFA execution.
Otherwise if it is NFA, you get NFA execution that only compiles
as-needed.
Some tests fail with assertion errors and may need to be debugged. There
is also a TODO about certain rewritemethods being incompatible, it might
be related to the failures.
So this change is not yet ready, but it demonstrates the idea.
If we can fix this in WildcardQuery too, we can remove the limit
parameter from QueryParsers completely, which is also a big bonus.
* Make thread-safe NFARunAutomaton
* style: autofix whitespace
* docs: move CHANGES entry to 11.0 for now, document thread safety fix
* docs: beef up CHANGES and add MIGRATE too
---------
Co-authored-by: Dimitris Rempapis <di...@elastic.co>
---
lucene/CHANGES.txt | 7 ++
lucene/MIGRATE.md | 15 +++
.../java/org/apache/lucene/search/RegexpQuery.java | 102 +-----------------
.../lucene/util/automaton/NFARunAutomaton.java | 114 ++++++++++++---------
.../lucene/search/TestDocValuesRewriteMethod.java | 30 +-----
.../lucene/search/TestFieldCacheRewriteMethod.java | 31 +-----
.../org/apache/lucene/search/TestRegexpQuery.java | 22 ++--
.../apache/lucene/search/TestRegexpRandom2.java | 4 +-
.../queryparser/classic/QueryParserBase.java | 7 +-
.../standard/builders/RegexpQueryNodeBuilder.java | 3 -
.../flexible/standard/TestQPHelper.java | 2 -
.../queryparser/util/QueryParserTestBase.java | 2 -
12 files changed, 109 insertions(+), 230 deletions(-)
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index f0274c83c98..90db96c0d55 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -76,6 +76,11 @@ API Changes
* GITHUB#15627 : Deferred lambda in TermStates.java according to prefetch (Shubham Sharma)
+* GITHUB#15939: Removed RegexpQuery constructor overloads that exposed determinization controls
+ (determinizeWorkLimit / doDeterminization). Determinization is now done only as-needed.
+ To force a classic DFA execution, use Operations.determinize() and AutomatonQuery.
+ (Dimitris Rempapis)
+
New Features
---------------------
* GITHUB#15505: Upgrade snowball to 2d2e312df56f2ede014a4ffb3e91e6dea43c24be. New stemmer: PolishStemmer (and
@@ -165,6 +170,8 @@ Bug Fixes
* GITHUB#15838: Fix luke terms export failure on Windows when field names contain characters forbidden in file name (Binlong Gao)
+* GITHUB#15939: Fix thread-safety issues with NFARunAutomaton. (Dimitris Rempapis)
+
Changes in Runtime Behavior
---------------------
* GITHUB#14187: The query cache is now disabled by default. (Adrien Grand)
diff --git a/lucene/MIGRATE.md b/lucene/MIGRATE.md
index 58dff66f68c..2a3eee9677d 100644
--- a/lucene/MIGRATE.md
+++ b/lucene/MIGRATE.md
@@ -159,6 +159,21 @@ iwc.getConfig().getCodec().compoundFormat().getShouldUseCompoundFile();
iwc.getConfig().getCodec().compoundFormat().getMaxCFSSegmentSizeMB();
```
+### Implicit determinization removed from RegexpQuery
+
+Previously, RegexpQuery would use DFA execution by default, even if it might be inefficient.
+
+RegexpQuery will now only [determinize as-needed](https://swtch.com/~rsc/regexp/regexp1.html). This might be
+faster or slower depending upon your queries.
+
+If you'd like to force the previous behavior, use `determinize()` and `AutomatonQuery`:
+
+```java
+String re = "a(b+|c+)d";
+Automaton dfa = Operations.determinize(new RegExp(re).toAutomaton(), 10000);
+Query query = new AutomatonQuery(new Term("myfield", re), dfa);
+```
+
## Migration from Lucene 10.4 to Lucene 10.5
### `[Byte|Float]VectorSimilarityQuery` now performs adaptive HNSW graph traversal
diff --git a/lucene/core/src/java/org/apache/lucene/search/RegexpQuery.java b/lucene/core/src/java/org/apache/lucene/search/RegexpQuery.java
index 72dcec0aae0..47cf72b73bb 100644
--- a/lucene/core/src/java/org/apache/lucene/search/RegexpQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/RegexpQuery.java
@@ -17,9 +17,7 @@
package org.apache.lucene.search;
import org.apache.lucene.index.Term;
-import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.AutomatonProvider;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
/**
@@ -64,21 +62,7 @@ public class RegexpQuery extends AutomatonQuery {
* @param flags optional RegExp features from {@link RegExp}
*/
public RegexpQuery(Term term, int flags) {
- this(term, flags, DEFAULT_PROVIDER, Operations.DEFAULT_DETERMINIZE_WORK_LIMIT);
- }
-
- /**
- * Constructs a query for terms matching <code>term</code>.
- *
- * @param term regular expression.
- * @param flags optional RegExp syntax features from {@link RegExp}
- * @param determinizeWorkLimit maximum effort to spend while compiling the automaton from this
- * regexp. Set higher to allow more complex queries and lower to prevent memory exhaustion.
- * Use {@link Operations#DEFAULT_DETERMINIZE_WORK_LIMIT} as a decent default if you don't
- * otherwise know what to specify.
- */
- public RegexpQuery(Term term, int flags, int determinizeWorkLimit) {
- this(term, flags, DEFAULT_PROVIDER, determinizeWorkLimit);
+ this(term, flags, 0);
}
/**
@@ -89,35 +73,9 @@ public class RegexpQuery extends AutomatonQuery {
* can result in. Set higher to allow more complex queries and lower to prevent memory
* exhaustion.
* @param matchFlags boolean 'or' of match behavior options such as case insensitivity
- * @param determinizeWorkLimit maximum effort to spend while compiling the automaton from this
- * regexp. Set higher to allow more complex queries and lower to prevent memory exhaustion.
- * Use {@link Operations#DEFAULT_DETERMINIZE_WORK_LIMIT} as a decent default if you don't
- * otherwise know what to specify.
*/
- public RegexpQuery(Term term, int syntaxFlags, int matchFlags, int determinizeWorkLimit) {
- this(
- term,
- syntaxFlags,
- matchFlags,
- DEFAULT_PROVIDER,
- determinizeWorkLimit,
- CONSTANT_SCORE_BLENDED_REWRITE);
- }
-
- /**
- * Constructs a query for terms matching <code>term</code>.
- *
- * @param term regular expression.
- * @param syntaxFlags optional RegExp features from {@link RegExp}
- * @param provider custom AutomatonProvider for named automata
- * @param determinizeWorkLimit maximum effort to spend while compiling the automaton from this
- * regexp. Set higher to allow more complex queries and lower to prevent memory exhaustion.
- * Use {@link Operations#DEFAULT_DETERMINIZE_WORK_LIMIT} as a decent default if you don't
- * otherwise know what to specify.
- */
- public RegexpQuery(
- Term term, int syntaxFlags, AutomatonProvider provider, int determinizeWorkLimit) {
- this(term, syntaxFlags, 0, provider, determinizeWorkLimit, CONSTANT_SCORE_BLENDED_REWRITE);
+ public RegexpQuery(Term term, int syntaxFlags, int matchFlags) {
+ this(term, syntaxFlags, matchFlags, DEFAULT_PROVIDER, CONSTANT_SCORE_BLENDED_REWRITE);
}
/**
@@ -127,10 +85,6 @@ public class RegexpQuery extends AutomatonQuery {
* @param syntaxFlags optional RegExp features from {@link RegExp}
* @param matchFlags boolean 'or' of match behavior options such as case insensitivity
* @param provider custom AutomatonProvider for named automata
- * @param determinizeWorkLimit maximum effort to spend while compiling the automaton from this
- * regexp. Set higher to allow more complex queries and lower to prevent memory exhaustion.
- * Use {@link Operations#DEFAULT_DETERMINIZE_WORK_LIMIT} as a decent default if you don't
- * otherwise know what to specify.
* @param rewriteMethod the rewrite method to use to build the final query
*/
public RegexpQuery(
@@ -138,62 +92,14 @@ public class RegexpQuery extends AutomatonQuery {
int syntaxFlags,
int matchFlags,
AutomatonProvider provider,
- int determinizeWorkLimit,
RewriteMethod rewriteMethod) {
- this(term, syntaxFlags, matchFlags, provider, determinizeWorkLimit, rewriteMethod, true);
- }
-
- /**
- * Constructs a query for terms matching <code>term</code>.
- *
- * @param term regular expression.
- * @param syntaxFlags optional RegExp features from {@link RegExp}
- * @param matchFlags boolean 'or' of match behavior options such as case insensitivity
- * @param provider custom AutomatonProvider for named automata
- * @param determinizeWorkLimit maximum effort to spend while compiling the automaton from this
- * regexp. Set higher to allow more complex queries and lower to prevent memory exhaustion.
- * Use {@link Operations#DEFAULT_DETERMINIZE_WORK_LIMIT} as a decent default if you don't
- * otherwise know what to specify.
- * @param rewriteMethod the rewrite method to use to build the final query
- * @param doDeterminization whether do determinization to force the query to use DFA as
- * runAutomaton, if false, the query will not try to determinize the generated automaton from
- * regexp such that it might or might not be a DFA. In case it is an NFA, the query will
- * eventually use {@link org.apache.lucene.util.automaton.NFARunAutomaton} to execute. Notice
- * that {@link org.apache.lucene.util.automaton.NFARunAutomaton} is not thread-safe, so better
- * to avoid rewritten method like {@link #CONSTANT_SCORE_BLENDED_REWRITE} when searcher is
- * configured with an executor service
- */
- public RegexpQuery(
- Term term,
- int syntaxFlags,
- int matchFlags,
- AutomatonProvider provider,
- int determinizeWorkLimit,
- RewriteMethod rewriteMethod,
- boolean doDeterminization) {
super(
term,
- toAutomaton(
- new RegExp(term.text(), syntaxFlags, matchFlags),
- determinizeWorkLimit,
- provider,
- doDeterminization),
+ new RegExp(term.text(), syntaxFlags, matchFlags).toAutomaton(provider),
false,
rewriteMethod);
}
- private static Automaton toAutomaton(
- RegExp regexp,
- int determinizeWorkLimit,
- AutomatonProvider provider,
- boolean doDeterminization) {
- if (doDeterminization) {
- return Operations.determinize(regexp.toAutomaton(provider), determinizeWorkLimit);
- } else {
- return regexp.toAutomaton(provider);
- }
- }
-
/** Returns the regexp of this query wrapped in a Term. */
public Term getRegexp() {
return term;
diff --git a/lucene/core/src/java/org/apache/lucene/util/automaton/NFARunAutomaton.java b/lucene/core/src/java/org/apache/lucene/util/automaton/NFARunAutomaton.java
index 7180e37d705..b407cdd01a0 100644
--- a/lucene/core/src/java/org/apache/lucene/util/automaton/NFARunAutomaton.java
+++ b/lucene/core/src/java/org/apache/lucene/util/automaton/NFARunAutomaton.java
@@ -27,7 +27,8 @@ import org.apache.lucene.util.RamUsageEstimator;
/**
* A RunAutomaton that does not require DFA. It will lazily determinize on-demand, memorizing the
- * generated DFA states that has been explored. Note: the current implementation is NOT thread-safe
+ * generated DFA states that has been explored. This implementation is thread-safe: multiple threads
+ * may concurrently step through different (or the same) DFA states.
*
* <p>implemented based on: https://swtch.com/~rsc/regexp/regexp1.html
*
@@ -45,15 +46,12 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
private final Automaton automaton;
private final int[] points;
- private final Map<DState, Integer> dStateToOrd = new HashMap<>(); // could init lazily?
+ private final Map<DState, Integer> dStateToOrd = new HashMap<>(); // guarded by stateRegistryLock
+ private final Object stateRegistryLock = new Object();
private DState[] dStates;
private final int alphabetSize;
final int[] classmap; // map from char number to class
- private final Operations.PointTransitionSet transitionSet =
- new Operations.PointTransitionSet(); // reusable
- private final StateSet statesSet = new StateSet(5); // reusable
-
/**
* Constructor, assuming alphabet size is the whole Unicode code point space
*
@@ -101,19 +99,20 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
*/
@Override
public int step(int state, int c) {
- assert dStates[state] != null;
- return step(dStates[state], c);
+ DState dState = getDState(state);
+ return step(dState, c);
}
@Override
public boolean isAccept(int state) {
- assert dStates[state] != null;
- return dStates[state].isAccept;
+ return getDState(state).isAccept;
}
@Override
public int getSize() {
- return dStates.length;
+ synchronized (stateRegistryLock) {
+ return dStates.length;
+ }
}
/**
@@ -128,7 +127,7 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
p = step(p, c);
if (p == MISSING) return false;
}
- return dStates[p].isAccept;
+ return getDState(p).isAccept;
}
/**
@@ -141,6 +140,13 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
return dState.nextState(charClass);
}
+ private DState getDState(int state) {
+ synchronized (stateRegistryLock) {
+ assert dStates[state] != null;
+ return dStates[state];
+ }
+ }
+
/**
* return the ordinal of given DFA state, generate a new ordinal if the given DFA state is a new
* one
@@ -149,18 +155,20 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
if (dState == null) {
return MISSING;
}
- int ord = dStateToOrd.getOrDefault(dState, -1);
- if (ord >= 0) {
+ synchronized (stateRegistryLock) {
+ int ord = dStateToOrd.getOrDefault(dState, -1);
+ if (ord >= 0) {
+ return ord;
+ }
+ ord = dStateToOrd.size();
+ dStateToOrd.put(dState, ord);
+ assert ord >= dStates.length || dStates[ord] == null;
+ if (ord >= dStates.length) {
+ dStates = ArrayUtil.grow(dStates, ord + 1);
+ }
+ dStates[ord] = dState;
return ord;
}
- ord = dStateToOrd.size();
- dStateToOrd.put(dState, ord);
- assert ord >= dStates.length || dStates[ord] == null;
- if (ord >= dStates.length) {
- dStates = ArrayUtil.grow(dStates, ord + 1);
- }
- dStates[ord] = dState;
- return ord;
}
/** Gets character class of given codepoint */
@@ -185,25 +193,31 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
@Override
public int initTransition(int state, Transition t) {
+ DState dState = getDState(state);
+ dState.determinize();
t.source = state;
t.transitionUpto = -1;
- return getNumTransitions(state);
+ return dState.outgoingTransitions;
}
@Override
public void getNextTransition(Transition t) {
- assert t.transitionUpto < points.length - 1 && t.transitionUpto >= -1;
- while (dStates[t.source].transitions[++t.transitionUpto] == MISSING) {
- // this shouldn't throw AIOOBE as long as this function is only called
- // numTransitions times
- }
- assert dStates[t.source].transitions[t.transitionUpto] != NOT_COMPUTED;
+ DState dState = getDState(t.source);
+ synchronized (dState) {
+ dState.determinize();
+ assert t.transitionUpto < points.length - 1 && t.transitionUpto >= -1;
+ while (dState.transitions[++t.transitionUpto] == MISSING) {
+ // this shouldn't throw AIOOBE as long as this function is only called
+ // numTransitions times
+ }
+ assert dState.transitions[t.transitionUpto] != NOT_COMPUTED;
- setTransitionAccordingly(t);
+ setTransitionAccordingly(t, dState);
+ }
}
- private void setTransitionAccordingly(Transition t) {
- t.dest = dStates[t.source].transitions[t.transitionUpto];
+ private void setTransitionAccordingly(Transition t, DState dState) {
+ t.dest = dState.transitions[t.transitionUpto];
t.min = points[t.transitionUpto];
if (t.transitionUpto == points.length - 1) {
t.max = alphabetSize - 1;
@@ -214,24 +228,28 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
@Override
public int getNumTransitions(int state) {
- dStates[state].determinize();
- return dStates[state].outgoingTransitions;
+ DState dState = getDState(state);
+ dState.determinize();
+ return dState.outgoingTransitions;
}
@Override
public void getTransition(int state, int index, Transition t) {
- dStates[state].determinize();
- int outgoingTransitions = -1;
- t.transitionUpto = -1;
- t.source = state;
- while (outgoingTransitions < index && t.transitionUpto < points.length - 1) {
- if (dStates[t.source].transitions[++t.transitionUpto] != MISSING) {
- outgoingTransitions++;
+ DState dState = getDState(state);
+ synchronized (dState) {
+ dState.determinize();
+ int outgoingTransitions = -1;
+ t.transitionUpto = -1;
+ t.source = state;
+ while (outgoingTransitions < index && t.transitionUpto < points.length - 1) {
+ if (dState.transitions[++t.transitionUpto] != MISSING) {
+ outgoingTransitions++;
+ }
}
- }
- assert outgoingTransitions == index;
+ assert outgoingTransitions == index;
- setTransitionAccordingly(t);
+ setTransitionAccordingly(t, dState);
+ }
}
@Override
@@ -270,7 +288,7 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
this.hashCode = hashCode;
}
- private int nextState(int charClass) {
+ private synchronized int nextState(int charClass) {
initTransitions();
assert charClass < transitions.length;
if (transitions[charClass] == NOT_COMPUTED) {
@@ -310,7 +328,7 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
* wrapped as a DFA state
*/
private DState step(int c) {
- statesSet.reset(); // TODO: fork IntHashSet from hppc instead?
+ StateSet statesSet = new StateSet(5);
int numTransitions;
int left = -1, right = alphabetSize;
for (int nfaState : nfaStates) {
@@ -343,13 +361,15 @@ public class NFARunAutomaton implements ByteRunnable, TransitionAccessor, Accoun
}
// determinize this state only
- private void determinize() {
+ private synchronized void determinize() {
if (transitions != null && computedTransitions == transitions.length) {
// already determinized
return;
}
initTransitions();
// Mostly forked from Operations.determinize
+ Operations.PointTransitionSet transitionSet = new Operations.PointTransitionSet();
+ StateSet statesSet = new StateSet(5);
transitionSet.reset();
for (int nfaState : nfaStates) {
int numTransitions = automaton.initTransition(nfaState, stepTransition);
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesRewriteMethod.java b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesRewriteMethod.java
index 17d63d28089..d7ff781cbc2 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDocValuesRewriteMethod.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDocValuesRewriteMethod.java
@@ -36,7 +36,6 @@ import org.apache.lucene.tests.util.TestUtil;
import org.apache.lucene.tests.util.automaton.AutomatonTestUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.UnicodeUtil;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
/** Tests the DocValuesRewriteMethod */
@@ -116,19 +115,13 @@ public class TestDocValuesRewriteMethod extends LuceneTestCase {
protected void assertSame(String regexp) throws IOException {
RegexpQuery docValues =
new RegexpQuery(
- new Term(fieldName, regexp),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, regexp), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery docValuesWithSkip =
new RegexpQuery(
new Term(fieldName + "_with-skip", regexp),
RegExp.NONE,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
new DocValuesRewriteMethod());
RegexpQuery inverted = new RegexpQuery(new Term(fieldName, regexp), RegExp.NONE);
@@ -152,28 +145,13 @@ public class TestDocValuesRewriteMethod extends LuceneTestCase {
{
RegexpQuery a1 =
new RegexpQuery(
- new Term(fieldName, "[aA]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[aA]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery a2 =
new RegexpQuery(
- new Term(fieldName, "[aA]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[aA]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery b =
new RegexpQuery(
- new Term(fieldName, "[bB]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[bB]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
assertEquals(a1, a2);
assertFalse(a1.equals(b));
QueryUtils.check(a1);
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestFieldCacheRewriteMethod.java b/lucene/core/src/test/org/apache/lucene/search/TestFieldCacheRewriteMethod.java
index 94962e81033..526568ba55b 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestFieldCacheRewriteMethod.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestFieldCacheRewriteMethod.java
@@ -20,7 +20,6 @@ import java.io.IOException;
import org.apache.lucene.index.Term;
import org.apache.lucene.tests.search.CheckHits;
import org.apache.lucene.tests.search.QueryUtils;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
/** Tests the FieldcacheRewriteMethod with random regular expressions */
@@ -31,12 +30,7 @@ public class TestFieldCacheRewriteMethod extends TestRegexpRandom2 {
protected void assertSame(String regexp) throws IOException {
RegexpQuery fieldCache =
new RegexpQuery(
- new Term(fieldName, regexp),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, regexp), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery filter =
new RegexpQuery(
@@ -44,7 +38,6 @@ public class TestFieldCacheRewriteMethod extends TestRegexpRandom2 {
RegExp.NONE,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
MultiTermQuery.CONSTANT_SCORE_REWRITE);
RegexpQuery filter2 =
@@ -53,7 +46,6 @@ public class TestFieldCacheRewriteMethod extends TestRegexpRandom2 {
RegExp.NONE,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE);
TopDocs fieldCacheDocs = searcher1.search(fieldCache, 25);
@@ -77,28 +69,13 @@ public class TestFieldCacheRewriteMethod extends TestRegexpRandom2 {
{
RegexpQuery a1 =
new RegexpQuery(
- new Term(fieldName, "[aA]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[aA]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery a2 =
new RegexpQuery(
- new Term(fieldName, "[aA]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[aA]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
RegexpQuery b =
new RegexpQuery(
- new Term(fieldName, "[bB]"),
- RegExp.NONE,
- 0,
- _ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- new DocValuesRewriteMethod());
+ new Term(fieldName, "[bB]"), RegExp.NONE, 0, _ -> null, new DocValuesRewriteMethod());
assertEquals(a1, a2);
assertFalse(a1.equals(b));
QueryUtils.check(a1);
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestRegexpQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestRegexpQuery.java
index 623f7904366..1db19250241 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestRegexpQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestRegexpQuery.java
@@ -16,8 +16,6 @@
*/
package org.apache.lucene.search;
-import static org.apache.lucene.util.automaton.Operations.DEFAULT_DETERMINIZE_WORK_LIMIT;
-
import java.io.IOException;
import java.util.Arrays;
import org.apache.lucene.document.Document;
@@ -32,7 +30,6 @@ import org.apache.lucene.util.automaton.Automaton;
import org.apache.lucene.util.automaton.AutomatonProvider;
import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
-import org.apache.lucene.util.automaton.TooComplexToDeterminizeException;
/** Some simple regex tests, mostly converted from contrib's TestRegexQuery. */
public class TestRegexpQuery extends LuceneTestCase {
@@ -81,9 +78,7 @@ public class TestRegexpQuery extends LuceneTestCase {
RegExp.ALL,
RegExp.ASCII_CASE_INSENSITIVE | RegExp.CASE_INSENSITIVE,
RegexpQuery.DEFAULT_PROVIDER,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
- MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE,
- random().nextBoolean());
+ MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE);
return searcher.count(query);
}
@@ -171,7 +166,11 @@ public class TestRegexpQuery extends LuceneTestCase {
};
RegexpQuery query =
new RegexpQuery(
- newTerm("<quickBrown>"), RegExp.ALL, myProvider, DEFAULT_DETERMINIZE_WORK_LIMIT);
+ newTerm("<quickBrown>"),
+ RegExp.ALL,
+ 0,
+ myProvider,
+ MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE);
assertEquals(1, searcher.search(query, 5).totalHits.value());
}
@@ -183,13 +182,4 @@ public class TestRegexpQuery extends LuceneTestCase {
public void testBacktracking() throws IOException {
assertEquals(1, regexQueryNrHits("4934[314]"));
}
-
- /** Test worst-case for getCommonSuffix optimization */
- public void testSlowCommonSuffix() throws Exception {
- expectThrows(
- TooComplexToDeterminizeException.class,
- () -> {
- new RegexpQuery(new Term("stringvalue", "(.*a){2000}"));
- });
- }
}
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestRegexpRandom2.java b/lucene/core/src/test/org/apache/lucene/search/TestRegexpRandom2.java
index 5f48b0861bb..df32f60c3c6 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestRegexpRandom2.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestRegexpRandom2.java
@@ -180,11 +180,9 @@ public class TestRegexpRandom2 extends LuceneTestCase {
RegExp.NONE,
0,
RegexpQuery.DEFAULT_PROVIDER,
- 0,
// TODO: The NFA query is not able to use rewrite method that will utilize the
// concurrency
- MultiTermQuery.CONSTANT_SCORE_BOOLEAN_REWRITE,
- false);
+ MultiTermQuery.CONSTANT_SCORE_BOOLEAN_REWRITE);
DumbRegexpQuery dumb = new DumbRegexpQuery(new Term(fieldName, regexp), RegExp.NONE);
TopDocs smartDocs = searcher1.search(smart, 25);
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java
index 0cb5a0900d6..e3c643b16f6 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/classic/QueryParserBase.java
@@ -570,12 +570,7 @@ public abstract class QueryParserBase extends QueryBuilder
*/
protected Query newRegexpQuery(Term regexp) {
return new RegexpQuery(
- regexp,
- RegExp.ALL,
- 0,
- RegexpQuery.DEFAULT_PROVIDER,
- determinizeWorkLimit,
- multiTermRewriteMethod);
+ regexp, RegExp.ALL, 0, RegexpQuery.DEFAULT_PROVIDER, multiTermRewriteMethod);
}
/**
diff --git a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/RegexpQueryNodeBuilder.java b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/RegexpQueryNodeBuilder.java
index 53ffae4ed33..d23a8e06542 100644
--- a/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/RegexpQueryNodeBuilder.java
+++ b/lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/standard/builders/RegexpQueryNodeBuilder.java
@@ -23,7 +23,6 @@ import org.apache.lucene.queryparser.flexible.standard.nodes.RegexpQueryNode;
import org.apache.lucene.queryparser.flexible.standard.processors.MultiTermRewriteMethodProcessor;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.RegexpQuery;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
/** Builds a {@link RegexpQuery} object from a {@link RegexpQueryNode} object. */
@@ -43,13 +42,11 @@ public class RegexpQueryNodeBuilder implements StandardQueryBuilder {
method = MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE;
}
- // TODO: make the maxStates configurable w/ a reasonable default (QueryParserBase uses 10000)
return new RegexpQuery(
new Term(regexpNode.getFieldAsString(), regexpNode.textToBytesRef()),
RegExp.ALL,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
method);
}
}
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java
index a8f45fa0262..8bdf2f4df2f 100644
--- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java
@@ -77,7 +77,6 @@ import org.apache.lucene.tests.analysis.MockTokenizer;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.util.automaton.Automata;
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -1201,7 +1200,6 @@ public class TestQPHelper extends LuceneTestCase {
RegExp.ALL,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
MultiTermQuery.SCORING_BOOLEAN_REWRITE);
assertEquals(new BoostQuery(q, 0.5f), qp.parse("/[A-Z][123]/^0.5", df));
assertEquals(
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java
index 5ec23428215..b178cecf5f9 100644
--- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/util/QueryParserTestBase.java
@@ -66,7 +66,6 @@ import org.apache.lucene.tests.analysis.MockTokenizer;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.util.automaton.Automata;
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
-import org.apache.lucene.util.automaton.Operations;
import org.apache.lucene.util.automaton.RegExp;
import org.junit.AfterClass;
import org.junit.BeforeClass;
@@ -1102,7 +1101,6 @@ public abstract class QueryParserTestBase extends LuceneTestCase {
RegExp.ALL,
0,
_ -> null,
- Operations.DEFAULT_DETERMINIZE_WORK_LIMIT,
MultiTermQuery.SCORING_BOOLEAN_REWRITE);
assertTrue(getQuery("/[A-Z][123]/^0.5", qp) instanceof BoostQuery);
assertTrue(((BoostQuery) getQuery("/[A-Z][123]/^0.5", qp)).getQuery() instanceof RegexpQuery);