2121import org .apache .paimon .data .BinaryString ;
2222import org .apache .paimon .types .DataType ;
2323import org .apache .paimon .utils .Filter ;
24+ import org .apache .paimon .utils .Pair ;
2425
2526import org .apache .paimon .shade .caffeine2 .com .github .benmanes .caffeine .cache .Cache ;
2627import org .apache .paimon .shade .caffeine2 .com .github .benmanes .caffeine .cache .Caffeine ;
2930
3031import java .util .List ;
3132import java .util .Optional ;
32- import java .util .regex .Matcher ;
3333import java .util .regex .Pattern ;
3434
35- import static org .apache .paimon .data .BinaryString .fromString ;
36-
3735/** A {@link NullFalseLeafBinaryFunction} to evaluate {@code filter like}. */
3836public class Like extends NullFalseLeafBinaryFunction {
3937
4038 public static final Like INSTANCE = new Like ();
4139
42- /** Accepts simple LIKE patterns like "abc%". */
43- private static final Pattern BEGIN_PATTERN = Pattern .compile ("([^%]+)%" );
44- /** Accepts simple LIKE patterns like "%abc". */
45- private static final Pattern END_PATTERN = Pattern .compile ("%([^%]+)" );
46- /** Accepts simple LIKE patterns like "%abc%". */
47- private static final Pattern MIDDLE_PATTERN = Pattern .compile ("%([^%]+)%" );
48- /** Accepts simple LIKE patterns like "abc". */
49- private static final Pattern NONE_PATTERN = Pattern .compile ("[^%]+" );
50-
5140 private static final Cache <BinaryString , Filter <BinaryString >> CACHE =
5241 Caffeine .newBuilder ().softValues ().executor (Runnable ::run ).build ();
5342
@@ -62,43 +51,23 @@ public boolean test(DataType type, Object field, Object patternLiteral) {
6251 BinaryString pattern = (BinaryString ) patternLiteral ;
6352 Filter <BinaryString > filter = CACHE .getIfPresent (pattern );
6453 if (filter == null ) {
65- filter = createFunc (pattern . toString () );
54+ filter = createFunc (type , patternLiteral );
6655 CACHE .put (pattern , filter );
6756 }
6857 return filter .test ((BinaryString ) field );
6958 }
7059
71- private Filter <BinaryString > createFunc (String pattern ) {
72- if (pattern .contains ("_" )) {
73- return createRegexFunc (pattern );
60+ private Filter <BinaryString > createFunc (DataType type , Object patternLiteral ) {
61+ Optional <Pair <NullFalseLeafBinaryFunction , Object >> optimized =
62+ LikeOptimization .tryOptimize (patternLiteral );
63+ if (optimized .isPresent ()) {
64+ NullFalseLeafBinaryFunction func = optimized .get ().getKey ();
65+ Object literal = optimized .get ().getValue ();
66+ return field -> func .test (type , field , literal );
7467 }
75-
76- Matcher noneMatcher = NONE_PATTERN .matcher (pattern );
77- Matcher beginMatcher = BEGIN_PATTERN .matcher (pattern );
78- Matcher endMatcher = END_PATTERN .matcher (pattern );
79- Matcher middleMatcher = MIDDLE_PATTERN .matcher (pattern );
80-
81- if (noneMatcher .matches ()) {
82- BinaryString equals = fromString (pattern );
83- return input -> input .equals (equals );
84- } else if (beginMatcher .matches ()) {
85- BinaryString begin = fromString (beginMatcher .group (1 ));
86- return input -> input .startsWith (begin );
87- } else if (endMatcher .matches ()) {
88- BinaryString end = fromString (endMatcher .group (1 ));
89- return input -> input .endsWith (end );
90- } else if (middleMatcher .matches ()) {
91- BinaryString middle = fromString (middleMatcher .group (1 ));
92- return input -> input .contains (middle );
93- } else {
94- return createRegexFunc (pattern );
95- }
96- }
97-
98- private Filter <BinaryString > createRegexFunc (String pattern ) {
99- String regex = sqlToRegexLike (pattern , null );
100- Pattern patternObject = Pattern .compile (regex );
101- return input -> patternObject .matcher (input .toString ()).matches ();
68+ String regex = sqlToRegexLike (patternLiteral .toString (), null );
69+ Pattern pattern = Pattern .compile (regex );
70+ return input -> pattern .matcher (input .toString ()).matches ();
10271 }
10372
10473 private static String sqlToRegexLike (String sqlPattern , @ Nullable CharSequence escapeStr ) {
0 commit comments