diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java index 9affa9cb6a..ddcedfd166 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java @@ -47,11 +47,16 @@ public enum SQLBinaryOperator { LessThanOrEqual("<=", 110), LessThanOrEqualOrGreaterThan("<=>",110), LessThanOrGreater("<>", 110), - Like("LIKE", 110), + + Like("LIKE", 110), + NotLike("NOT LIKE", 110), + + RLike("RLIKE", 110), + NotRLike("NOT RLIKE", 110), + NotEqual("!=", 110), NotLessThan("!<", 110), NotGreaterThan("!>", 110), - NotLike("NOT LIKE", 110), IsNot("IS NOT", 110), Escape("ESCAPE", 110), RegExp("REGEXP", 110), diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index eafd822812..6847923b07 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -52,7 +52,16 @@ public class MySqlExprParser extends SQLExprParser { } public SQLExpr relationalRest(SQLExpr expr) throws ParserException { - if (lexer.token() == Token.IDENTIFIER && "REGEXP".equalsIgnoreCase(lexer.stringVal())) { + if (identifierEquals("REGEXP")) { + lexer.nextToken(); + SQLExpr rightExp = equality(); + + rightExp = relationalRest(rightExp); + + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.RegExp, rightExp); + } + + if (identifierEquals("RLIKE")) { lexer.nextToken(); SQLExpr rightExp = equality(); @@ -78,7 +87,7 @@ public class MySqlExprParser extends SQLExprParser { } public SQLExpr notRationalRest(SQLExpr expr) { - if (lexer.token() == Token.IDENTIFIER && "REGEXP".equalsIgnoreCase(lexer.stringVal())) { + if (identifierEquals("REGEXP")) { lexer.nextToken(); SQLExpr rightExp = primary(); @@ -86,6 +95,15 @@ public class MySqlExprParser extends SQLExprParser { return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRegExp, rightExp); } + + if (identifierEquals("RLIKE")) { + lexer.nextToken(); + SQLExpr rightExp = primary(); + + rightExp = relationalRest(rightExp); + + return new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotRLike, rightExp); + } return super.notRationalRest(expr); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 7f98ef2ced..2808049a00 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -149,6 +149,8 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle public OracleSchemaStatVisitor(){ this.variants.put("DUAL", null); this.variants.put("NOTFOUND", null); + this.variants.put("TRUE", null); + this.variants.put("FALSE", null); } protected Column getColumn(SQLExpr expr) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index af953c8173..7f67fa595b 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -217,6 +217,7 @@ public class SQLExprParser extends SQLParser { case SCHEMA: case AT: case COLUMN: + case IF: sqlExpr = new SQLIdentifierExpr(lexer.stringVal()); lexer.nextToken(); break; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index fa6c5507f1..12c46ff580 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -14,6 +14,7 @@ import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLCurrentOfCursorExpr; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLInSubQueryExpr; @@ -867,4 +868,8 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLCommentStatement x) { return false; } + + public boolean visit(SQLCurrentOfCursorExpr x) { + return false; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_3.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_3.java new file mode 100644 index 0000000000..b2643ab93c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_3.java @@ -0,0 +1,39 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_3 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT 'Monty!' REGEXP '.*'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_4.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_4.java new file mode 100644 index 0000000000..b5d836ac76 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_4.java @@ -0,0 +1,39 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; + +public class MySqlSelectTest_4 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT 'Monty!' NOT REGEXP '.*'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_5.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_5.java new file mode 100644 index 0000000000..b5cccd2d2d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_5.java @@ -0,0 +1,38 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlSelectTest_5 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT 'Monty!' RLIKE '.*'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_6.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_6.java new file mode 100644 index 0000000000..4006b3404d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlSelectTest_6.java @@ -0,0 +1,38 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlSelectTest_6 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT 'Monty!' NOT RLIKE '.*'"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + System.out.println("coditions : " + visitor.getConditions()); + System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + } +} diff --git a/src/test/java/com/alibaba/druid/mysql/MySqlBigTableTest.java b/src/test/java/com/alibaba/druid/mysql/MySqlBigTableTest.java new file mode 100644 index 0000000000..ddfe3f45f0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/mysql/MySqlBigTableTest.java @@ -0,0 +1,113 @@ +package com.alibaba.druid.mysql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +import junit.framework.TestCase; + +import com.alibaba.druid.pool.DruidDataSource; + +public class MySqlBigTableTest extends TestCase { + final int COUNT = 800; + + private String jdbcUrl; + private String user; + private String password; + private String driverClass; + + private DruidDataSource dataSource; + + protected void setUp() throws Exception { + jdbcUrl = "jdbc:mysql://10.20.144.27:3306/dragoon_v25_masterdb"; + user = "dragoon_test"; + password = "dragoon_test"; + driverClass = "com.mysql.jdbc.Driver"; + + dataSource = new DruidDataSource(); + dataSource.setDriverClassName(driverClass); + dataSource.setUrl(jdbcUrl); + dataSource.setPoolPreparedStatements(true); + dataSource.setUsername(user); + dataSource.setPassword(password); + + createTable(); + } + + protected void tearDown() throws Exception { + try { + dropTable(); + } catch (SQLException e) { + e.printStackTrace(); + } + + if (dataSource != null) { + dataSource.close(); + } + } + + public void test_0() throws Exception { + + StringBuffer ddl = new StringBuffer(); + ddl.append("INSERT INTO t_big ("); + for (int i = 0; i < COUNT; ++i) { + if (i != 0) { + ddl.append(", "); + } + ddl.append("F" + i); + } + ddl.append(") VALUES ("); + for (int i = 0; i < COUNT; ++i) { + if (i != 0) { + ddl.append(", "); + } + ddl.append("?"); + } + ddl.append(")"); + + Connection conn = dataSource.getConnection(); + + System.out.println(ddl.toString()); + + PreparedStatement stmt = conn.prepareStatement(ddl.toString()); + + for (int i = 0; i < COUNT; ++i) { + stmt.setInt(i + 1, i); + } + stmt.execute(); + stmt.close(); + + conn.close(); + } + + private void dropTable() throws SQLException { + + Connection conn = dataSource.getConnection(); + + Statement stmt = conn.createStatement(); + stmt.execute("DROP TABLE t_big"); + stmt.close(); + + conn.close(); + } + + private void createTable() throws SQLException { + StringBuffer ddl = new StringBuffer(); + ddl.append("CREATE TABLE t_big (FID INT AUTO_INCREMENT PRIMARY KEY "); + for (int i = 0; i < COUNT; ++i) { + ddl.append(", "); + ddl.append("F" + i); + ddl.append(" BIGINT NULL"); + } + ddl.append(")"); + + Connection conn = dataSource.getConnection(); + + Statement stmt = conn.createStatement(); + stmt.execute(ddl.toString()); + stmt.close(); + + conn.close(); + } +}