From 4d9e46198e0a679c7d7f05d0ef43558fc65a2d51 Mon Sep 17 00:00:00 2001 From: Sarah Komla-Ebri Date: Wed, 16 Jul 2014 15:27:25 +0200 Subject: [PATCH 1/3] Added support for MySQL REGEXP insensitivity case --- .../expression/ExpressionVisitor.java | 3 + .../expression/ExpressionVisitorAdapter.java | 5 ++ .../relational/RegExpMySQLOperator.java | 58 +++++++++++++++++++ .../sf/jsqlparser/util/TablesNamesFinder.java | 7 +++ .../util/deparser/ExpressionDeParser.java | 7 +++ .../net/sf/jsqlparser/parser/JSqlParserCC.jj | 3 + .../sf/jsqlparser/test/select/SelectTest.java | 5 ++ 7 files changed, 88 insertions(+) create mode 100644 src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMySQLOperator.java diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java index aa1a6b425..16a562201 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java @@ -45,6 +45,7 @@ import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals; import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo; import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator; +import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.statement.select.SubSelect; @@ -145,4 +146,6 @@ public interface ExpressionVisitor { void visit(RegExpMatchOperator rexpr); void visit(JsonExpression jsonExpr); + + void visit(RegExpMySQLOperator regExpMySQLOperator); } diff --git a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java index e2b5c1c2d..21c94652d 100644 --- a/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java +++ b/src/main/java/net/sf/jsqlparser/expression/ExpressionVisitorAdapter.java @@ -307,4 +307,9 @@ protected void visitBinaryExpression(BinaryExpression expr) { public void visit(JsonExpression jsonExpr) { visit(jsonExpr.getColumn()); } + + @Override + public void visit(RegExpMySQLOperator expr) { + visitBinaryExpression(expr); + } } diff --git a/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMySQLOperator.java b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMySQLOperator.java new file mode 100644 index 000000000..2585eed43 --- /dev/null +++ b/src/main/java/net/sf/jsqlparser/expression/operators/relational/RegExpMySQLOperator.java @@ -0,0 +1,58 @@ +/* + * #%L + * JSQLParser library + * %% + * Copyright (C) 2004 - 2013 JSQLParser + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 2.1 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * . + * #L% + */ +package net.sf.jsqlparser.expression.operators.relational; + +import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.ExpressionVisitor; + +public class RegExpMySQLOperator extends BinaryExpression { + + private RegExpMatchOperatorType operatorType; + + public RegExpMySQLOperator(RegExpMatchOperatorType operatorType) { + if (operatorType == null) { + throw new NullPointerException(); + } + this.operatorType = operatorType; + } + + public RegExpMatchOperatorType getOperatorType() { + return operatorType; + } + + @Override + public void accept(ExpressionVisitor expressionVisitor) { + expressionVisitor.visit(this); + } + + @Override + public String getStringExpression() { + switch (operatorType) { + case MATCH_CASESENSITIVE: + return "REGEXP BINARY"; + case MATCH_CASEINSENSITIVE: + return "REGEXP"; + default: + } + return null; + } +} diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 61314dad7..6ae74b075 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -462,7 +462,14 @@ public void visit(RegExpMatchOperator rexpr) { visitBinaryExpression(rexpr); } + @Override + public void visit(RegExpMySQLOperator rexpr) { + visitBinaryExpression(rexpr); + } + @Override public void visit(JsonExpression jsonExpr) { } + + } diff --git a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java index f5b161ac6..a23ce95e0 100644 --- a/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java +++ b/src/main/java/net/sf/jsqlparser/util/deparser/ExpressionDeParser.java @@ -501,8 +501,15 @@ public void visit(RegExpMatchOperator rexpr) { visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); } + @Override + public void visit(RegExpMySQLOperator rexpr) { + visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " "); + } + @Override public void visit(JsonExpression jsonExpr) { buffer.append(jsonExpr.toString()); } + + } diff --git a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj index 481eb71bd..017b51c52 100644 --- a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj +++ b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj @@ -195,6 +195,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| + } TOKEN : /* Numeric Constants */ @@ -1278,6 +1280,7 @@ Expression RegularCondition(): | "!=" { result = new NotEqualsTo("!="); } | "@@" { result = new Matches(); } | "~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } + | { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } | "~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } | "!~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE); } | "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); } diff --git a/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java index 49d6e0d59..2cf4cc25d 100644 --- a/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java @@ -1325,6 +1325,11 @@ public void testRegexpLike2() throws JSQLParserException { String stmt = "SELECT CASE WHEN REGEXP_LIKE(first_name, '^Ste(v|ph)en$') THEN 1 ELSE 2 END FROM mytable"; assertSqlCanBeParsedAndDeparsed(stmt); } + + public void testRegexpMySQL() throws JSQLParserException { + String stmt = "SELECT * FROM mytable WHERE first_name REGEXP '^Ste(v|ph)en$'"; + assertSqlCanBeParsedAndDeparsed(stmt); + } public void testBooleanFunction1() throws JSQLParserException { String stmt = "SELECT * FROM mytable WHERE test_func(col1)"; From ec0dc88bc9b4280be3c0e5ccd698c6f6aecebd8b Mon Sep 17 00:00:00 2001 From: Sarah Komla-Ebri Date: Wed, 16 Jul 2014 15:50:37 +0200 Subject: [PATCH 2/3] Added support for MySQL REGEXP BINARY (for case insensitivity) --- src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj | 5 +++-- src/test/java/net/sf/jsqlparser/test/select/SelectTest.java | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj index 017b51c52..f5427554c 100644 --- a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj +++ b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj @@ -195,8 +195,8 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| - +| +| } TOKEN : /* Numeric Constants */ @@ -1281,6 +1281,7 @@ Expression RegularCondition(): | "@@" { result = new Matches(); } | "~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } | { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } + | { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } | "~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } | "!~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE); } | "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); } diff --git a/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java b/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java index 2cf4cc25d..fbbc50428 100644 --- a/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java +++ b/src/test/java/net/sf/jsqlparser/test/select/SelectTest.java @@ -1330,6 +1330,11 @@ public void testRegexpMySQL() throws JSQLParserException { String stmt = "SELECT * FROM mytable WHERE first_name REGEXP '^Ste(v|ph)en$'"; assertSqlCanBeParsedAndDeparsed(stmt); } + + public void testRegexpBinaryMySQL() throws JSQLParserException { + String stmt = "SELECT * FROM mytable WHERE first_name REGEXP BINARY '^Ste(v|ph)en$'"; + assertSqlCanBeParsedAndDeparsed(stmt); + } public void testBooleanFunction1() throws JSQLParserException { String stmt = "SELECT * FROM mytable WHERE test_func(col1)"; From 75aeded181a6f8869b6dc3ea5f19f26c27c35c8b Mon Sep 17 00:00:00 2001 From: Sarah Komla-Ebri Date: Wed, 16 Jul 2014 17:05:30 +0200 Subject: [PATCH 3/3] added lookahead for regexp binary --- src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj index f5427554c..dffd25ccf 100644 --- a/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj +++ b/src/main/javacc/net/sf/jsqlparser/parser/JSqlParserCC.jj @@ -195,7 +195,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| +| | } @@ -1280,8 +1280,8 @@ Expression RegularCondition(): | "!=" { result = new NotEqualsTo("!="); } | "@@" { result = new Matches(); } | "~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } + | LOOKAHEAD(2) { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } | { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } - | { result = new RegExpMySQLOperator(RegExpMatchOperatorType.MATCH_CASESENSITIVE); } | "~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.MATCH_CASEINSENSITIVE); } | "!~" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASESENSITIVE); } | "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); }