Skip to content

Commit

Permalink
Avoid exponential DFA in LIKE matcher
Browse files Browse the repository at this point in the history
When a pattern contains a % and a sequence of _ somewhere
after it, it may produce a DFA with exponential number of states.
In such cases, fall back to the NFA matcher.
  • Loading branch information
martint committed Sep 25, 2023
1 parent 9e48b3f commit e1dc146
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,24 @@ else if (expression instanceof Any any) {
Optional<Matcher> matcher = Optional.empty();
if (patternStart <= patternEnd) {
boolean hasAny = false;
boolean hasAnyAfterZeroOrMore = false;
boolean foundZeroOrMore = false;
for (int i = patternStart; i <= patternEnd; i++) {
if (parsed.get(i) instanceof Any) {
Pattern item = parsed.get(i);
if (item instanceof Any) {
if (foundZeroOrMore) {
hasAnyAfterZeroOrMore = true;
}
hasAny = true;
break;
}
else if (item instanceof Pattern.ZeroOrMore) {
foundZeroOrMore = true;
}
}

if (hasAny) {
if (optimize) {
if (optimize && !hasAnyAfterZeroOrMore) {
matcher = Optional.of(new DenseDfaMatcher(parsed, patternStart, patternEnd, exact));
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.google.common.base.Strings;
import io.trino.type.LikePattern;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;

import java.nio.charset.StandardCharsets;
import java.util.Optional;
Expand Down Expand Up @@ -110,6 +111,13 @@ public void test()
}
}

@Test
@Timeout(2)
public void testExponentialBehavior()
{
assertTrue(match("%a________________", "xyza1234567890123456"));
}

@Test
public void testEscape()
{
Expand Down

0 comments on commit e1dc146

Please sign in to comment.