Skip to content

Commit f132547

Browse files
feat: MySQL NOT RLIKE, NOT REGEXP expressions
- fixes #1553 - remove RegExpMySQLOperator, replaced by flavoured `LIKE` expression Signed-off-by: Andreas Reichel <[email protected]>
1 parent 386dc7a commit f132547

File tree

10 files changed

+73
-116
lines changed

10 files changed

+73
-116
lines changed

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
4545
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
4646
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
47-
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
4847
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
4948
import net.sf.jsqlparser.schema.Column;
5049
import net.sf.jsqlparser.statement.select.AllColumns;
@@ -168,8 +167,6 @@ public interface ExpressionVisitor {
168167

169168
void visit(JsonOperator jsonExpr);
170169

171-
void visit(RegExpMySQLOperator regExpMySQLOperator);
172-
173170
void visit(UserVariable var);
174171

175172
void visit(NumericBind bind);

src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
4545
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
4646
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
47-
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
4847
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
4948
import net.sf.jsqlparser.schema.Column;
5049
import net.sf.jsqlparser.statement.select.AllColumns;
@@ -433,11 +432,6 @@ public void visit(JsonOperator expr) {
433432
visitBinaryExpression(expr);
434433
}
435434

436-
@Override
437-
public void visit(RegExpMySQLOperator expr) {
438-
visitBinaryExpression(expr);
439-
}
440-
441435
@Override
442436
public void visit(UserVariable var) {
443437

src/main/java/net/sf/jsqlparser/expression/operators/relational/LikeExpression.java

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,18 @@
1414
import net.sf.jsqlparser.expression.ExpressionVisitor;
1515

1616
public class LikeExpression extends BinaryExpression {
17+
public enum KeyWord {
18+
LIKE, ILIKE, RLIKE, REGEXP;
19+
20+
public static KeyWord from(String keyword) {
21+
return Enum.valueOf(KeyWord.class, keyword.toUpperCase());
22+
}
23+
}
1724

1825
private boolean not = false;
26+
private boolean useBinary = false;
1927
private Expression escapeExpression = null;
20-
private boolean caseInsensitive = false;
28+
private KeyWord likeKeyWord = KeyWord.LIKE;
2129

2230
public boolean isNot() {
2331
return not;
@@ -27,23 +35,33 @@ public void setNot(boolean b) {
2735
not = b;
2836
}
2937

38+
public boolean isUseBinary() {
39+
return useBinary;
40+
}
41+
42+
public LikeExpression setUseBinary(boolean useBinary) {
43+
this.useBinary = useBinary;
44+
return this;
45+
}
46+
3047
@Override
3148
public void accept(ExpressionVisitor expressionVisitor) {
3249
expressionVisitor.visit(this);
3350
}
3451

52+
@Deprecated
3553
@Override
3654
public String getStringExpression() {
37-
return caseInsensitive ? "ILIKE" : "LIKE";
55+
return likeKeyWord.toString();
3856
}
3957

4058
@Override
4159
public String toString() {
42-
String retval = getLeftExpression() + " " + (not ? "NOT " : "") + getStringExpression() + " " + getRightExpression();
60+
String retval = getLeftExpression() + " " + (not ? "NOT " : "")
61+
+ likeKeyWord + " " + (useBinary ? "BINARY " : "") + getRightExpression();
4362
if (escapeExpression != null) {
44-
retval += " ESCAPE " + escapeExpression ;
63+
retval += " ESCAPE " + escapeExpression;
4564
}
46-
4765
return retval;
4866
}
4967

@@ -55,19 +73,36 @@ public void setEscape(Expression escapeExpression) {
5573
this.escapeExpression = escapeExpression;
5674
}
5775

76+
@Deprecated
5877
public boolean isCaseInsensitive() {
59-
return caseInsensitive;
78+
return likeKeyWord == KeyWord.ILIKE;
6079
}
6180

81+
@Deprecated
6282
public void setCaseInsensitive(boolean caseInsensitive) {
63-
this.caseInsensitive = caseInsensitive;
83+
this.likeKeyWord = KeyWord.ILIKE;
84+
}
85+
86+
public KeyWord getLikeKeyWord() {
87+
return likeKeyWord;
88+
}
89+
90+
public LikeExpression setLikeKeyWord(KeyWord likeKeyWord) {
91+
this.likeKeyWord = likeKeyWord;
92+
return this;
93+
}
94+
95+
public LikeExpression setLikeKeyWord(String likeKeyWord) {
96+
this.likeKeyWord = KeyWord.from(likeKeyWord);
97+
return this;
6498
}
6599

66100
public LikeExpression withEscape(Expression escape) {
67101
this.setEscape(escape);
68102
return this;
69103
}
70104

105+
@Deprecated
71106
public LikeExpression withCaseInsensitive(boolean caseInsensitive) {
72107
this.setCaseInsensitive(caseInsensitive);
73108
return this;

src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMySQLOperator.java

Lines changed: 0 additions & 74 deletions
This file was deleted.

src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@
9696
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
9797
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
9898
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
99-
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
10099
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
101100
import net.sf.jsqlparser.schema.Column;
102101
import net.sf.jsqlparser.schema.Table;
@@ -659,11 +658,6 @@ public void visit(RegExpMatchOperator rexpr) {
659658
visitBinaryExpression(rexpr);
660659
}
661660

662-
@Override
663-
public void visit(RegExpMySQLOperator rexpr) {
664-
visitBinaryExpression(rexpr);
665-
}
666-
667661
@Override
668662
public void visit(JsonExpression jsonExpr) {
669663

src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@
9898
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
9999
import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression;
100100
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
101-
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
102101
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
103102
import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax;
104103
import net.sf.jsqlparser.schema.Column;
@@ -330,8 +329,17 @@ public void visit(JdbcParameter jdbcParameter) {
330329

331330
@Override
332331
public void visit(LikeExpression likeExpression) {
333-
visitBinaryExpression(likeExpression, (likeExpression.isNot() ? " NOT" : "")
334-
+ (likeExpression.isCaseInsensitive() ? " ILIKE " : " LIKE "));
332+
likeExpression.getLeftExpression().accept(this);
333+
buffer.append(" ");
334+
if (likeExpression.isNot()) {
335+
buffer.append("NOT ");
336+
}
337+
buffer.append(likeExpression.getLikeKeyWord()).append(" ");
338+
if (likeExpression.isUseBinary()) {
339+
buffer.append("BINARY ");
340+
}
341+
likeExpression.getRightExpression().accept(this);
342+
335343
Expression escape = likeExpression.getEscape();
336344
if (escape != null) {
337345
buffer.append(" ESCAPE ");
@@ -847,10 +855,6 @@ public void visit(RegExpMatchOperator rexpr) {
847855
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
848856
}
849857

850-
@Override
851-
public void visit(RegExpMySQLOperator rexpr) {
852-
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
853-
}
854858

855859
@Override
856860
public void visit(JsonExpression jsonExpr) {

src/main/java/net/sf/jsqlparser/util/validation/validator/ExpressionValidator.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@
9999
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
100100
import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression;
101101
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
102-
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
103102
import net.sf.jsqlparser.expression.operators.relational.SimilarToExpression;
104103
import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax;
105104
import net.sf.jsqlparser.parser.feature.Feature;
@@ -481,11 +480,6 @@ public void visit(RegExpMatchOperator rexpr) {
481480
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
482481
}
483482

484-
@Override
485-
public void visit(RegExpMySQLOperator rexpr) {
486-
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
487-
}
488-
489483
@Override
490484
public void visit(JsonExpression jsonExpr) {
491485
validateOptionalExpression(jsonExpr.getExpression());

src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3270,8 +3270,6 @@ Expression RegularCondition() #RegularCondition:
32703270
| token=<OP_NOTEQUALSBANG> { result = new NotEqualsTo(token.image); }
32713271
| "@@" { result = new Matches(); }
32723272
| "~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); }
3273-
| [<K_NOT> { not=true; } ] <K_REGEXP> [ LOOKAHEAD(2) <K_BINARY> { binary=true; } ] { result = new RegExpMySQLOperator(not, binary?RegExpMatchOperatorType.MATCH_CASESENSITIVE:RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); }
3274-
| <K_RLIKE> [ LOOKAHEAD(2) <K_BINARY> { binary=true; } ] { result = new RegExpMySQLOperator(binary?RegExpMatchOperatorType.MATCH_CASESENSITIVE:RegExpMatchOperatorType.MATCH_CASEINSENSITIVE).useRLike(); }
32753273
| "~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); }
32763274
| "!~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE); }
32773275
| "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); }
@@ -3400,7 +3398,15 @@ Expression LikeExpression(Expression leftExpression) #LikeExpression:
34003398
Token token;
34013399
}
34023400
{
3403-
[<K_NOT> { result.setNot(true); } ] ( <K_LIKE> | <K_ILIKE> { result.setCaseInsensitive(true); } ) rightExpression=SimpleExpression()
3401+
[<K_NOT> { result.setNot(true); } ]
3402+
(
3403+
token = <K_LIKE>
3404+
| token = <K_ILIKE>
3405+
| token = <K_RLIKE>
3406+
| token = <K_REGEXP>
3407+
) { result.setLikeKeyWord( LikeExpression.KeyWord.from(token.image)); }
3408+
[ <K_BINARY> {result.setUseBinary(true); } ]
3409+
rightExpression=SimpleExpression()
34043410
[ LOOKAHEAD(2) <K_ESCAPE>
34053411
(
34063412
LOOKAHEAD(2) token = <S_CHAR_LITERAL> { result.setEscape( new StringValue( token.image ) ); }

src/test/java/net/sf/jsqlparser/expression/operators/relational/LikeExpressionTest.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import net.sf.jsqlparser.expression.Expression;
1414
import net.sf.jsqlparser.expression.StringValue;
1515
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
16+
import net.sf.jsqlparser.test.TestUtils;
1617
import org.junit.jupiter.api.Test;
1718

1819
import static org.junit.jupiter.api.Assertions.*;
@@ -32,12 +33,20 @@ public void testLikeNotIssue660() {
3233

3334
@Test
3435
public void testSetEscapeAndGetStringExpression() throws JSQLParserException {
35-
LikeExpression instance = (LikeExpression) CCJSqlParserUtil.parseExpression("name LIKE 'J%$_%'");
36+
LikeExpression instance =
37+
(LikeExpression) CCJSqlParserUtil.parseExpression("name LIKE 'J%$_%'");
3638
// escape character should be $
3739
Expression instance2 = new StringValue("$");
3840
instance.setEscape(instance2);
3941

40-
// match all records with names that start with letter ’J’ and have the ’_’ character in them
42+
// match all records with names that start with letter ’J’ and have the ’_’ character in
43+
// them
4144
assertEquals("name LIKE 'J%$_%' ESCAPE '$'", instance.toString());
4245
}
46+
47+
@Test
48+
void testNotRLikeIssue1553() throws JSQLParserException {
49+
String sqlStr = "select * from test where id not rlike '111'";
50+
TestUtils.assertSqlCanBeParsedAndDeparsed(sqlStr, true);
51+
}
4352
}

src/test/java/net/sf/jsqlparser/statement/builder/ReflectionModelTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ public class ReflectionModelTest {
118118
new net.sf.jsqlparser.expression.operators.relational.NotEqualsTo(),
119119
new net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator(
120120
RegExpMatchOperatorType.MATCH_CASEINSENSITIVE),
121-
new net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator(
122-
RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE),
123121
new net.sf.jsqlparser.expression.operators.relational.SimilarToExpression(),
124122
new net.sf.jsqlparser.schema.Column(), new net.sf.jsqlparser.schema.Database("db"),
125123
new net.sf.jsqlparser.schema.Sequence(),

0 commit comments

Comments
 (0)