mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser
This commit is contained in:
+9
@@ -30,6 +30,7 @@ public class MySqlInsertStatement extends SQLInsertStatement {
|
||||
private boolean delayed = false;
|
||||
private boolean highPriority = false;
|
||||
private boolean ignore = false;
|
||||
private boolean rollbackOnFail = false;
|
||||
|
||||
private final List<SQLExpr> duplicateKeyUpdate = new ArrayList<SQLExpr>();
|
||||
|
||||
@@ -69,6 +70,14 @@ public class MySqlInsertStatement extends SQLInsertStatement {
|
||||
this.ignore = ignore;
|
||||
}
|
||||
|
||||
public boolean isRollbackOnFail() {
|
||||
return rollbackOnFail;
|
||||
}
|
||||
|
||||
public void setRollbackOnFail(boolean rollbackOnFail) {
|
||||
this.rollbackOnFail = rollbackOnFail;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor instanceof MySqlASTVisitor) {
|
||||
|
||||
@@ -249,11 +249,17 @@ public class MySqlLexer extends Lexer {
|
||||
|
||||
mark = pos;
|
||||
bufPos = 1;
|
||||
char ch;
|
||||
char ch = '\0', last_ch;
|
||||
for (;;) {
|
||||
last_ch = ch;
|
||||
ch = charAt(++pos);
|
||||
|
||||
if (!isIdentifierChar(ch)) {
|
||||
if (last_ch == '-' && charAt(pos-2) != '-') {
|
||||
ch = last_ch;
|
||||
bufPos--;
|
||||
pos--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+29
-15
@@ -1936,24 +1936,38 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
if (lexer.token() == Token.INSERT) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (identifierEquals(LOW_PRIORITY)) {
|
||||
insertStatement.setLowPriority(true);
|
||||
lexer.nextToken();
|
||||
}
|
||||
for (;;) {
|
||||
if (identifierEquals(LOW_PRIORITY)) {
|
||||
insertStatement.setLowPriority(true);
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identifierEquals(DELAYED)) {
|
||||
insertStatement.setDelayed(true);
|
||||
lexer.nextToken();
|
||||
}
|
||||
if (identifierEquals(DELAYED)) {
|
||||
insertStatement.setDelayed(true);
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identifierEquals("HIGH_PRIORITY")) {
|
||||
insertStatement.setHighPriority(true);
|
||||
lexer.nextToken();
|
||||
}
|
||||
if (identifierEquals("HIGH_PRIORITY")) {
|
||||
insertStatement.setHighPriority(true);
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identifierEquals(IGNORE)) {
|
||||
insertStatement.setIgnore(true);
|
||||
lexer.nextToken();
|
||||
if (identifierEquals(IGNORE)) {
|
||||
insertStatement.setIgnore(true);
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (identifierEquals("ROLLBACK_ON_FAIL")) {
|
||||
insertStatement.setRollbackOnFail(true);
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.INTO) {
|
||||
|
||||
@@ -941,6 +941,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
if (x.isIgnore()) {
|
||||
print0(ucase ? "IGNORE " : "ignore ");
|
||||
}
|
||||
|
||||
if (x.isRollbackOnFail()) {
|
||||
print0(ucase ? "ROLLBACK_ON_FAIL " : "rollback_on_fail ");
|
||||
}
|
||||
|
||||
print0(ucase ? "INTO " : "into ");
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2101 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.bvt.sql.mysql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
|
||||
public class MySqlInsertTest_11 extends MysqlTest {
|
||||
|
||||
public void test_insert_rollback_on_fail() throws Exception {
|
||||
String sql = "insert ROLLBACK_ON_FAIL into t(a,b) values ('a1','b1')";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
parser.setParseCompleteValues(false);
|
||||
parser.setParseValuesSize(3);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
|
||||
MySqlInsertStatement insertStmt = (MySqlInsertStatement) stmt;
|
||||
|
||||
Assert.assertEquals(1, insertStmt.getValuesList().size());
|
||||
Assert.assertEquals(2, insertStmt.getValues().getValues().size());
|
||||
Assert.assertEquals(2, insertStmt.getColumns().size());
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.accept(visitor);
|
||||
|
||||
String formatSql = "INSERT ROLLBACK_ON_FAIL INTO t (a, b)"//
|
||||
+ "\nVALUES ('a1', 'b1')";
|
||||
Assert.assertEquals(formatSql, SQLUtils.toMySqlString(insertStmt));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 1999-2101 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.druid.bvt.sql.mysql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
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;
|
||||
import com.alibaba.druid.stat.TableStat.Column;
|
||||
|
||||
public class MySqlUpdateTest_8 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "update haskell_function set `arity` = arity-'1' where id = 1;";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
print(statementList);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.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(1, visitor.getTables().size());
|
||||
Assert.assertEquals(2, visitor.getColumns().size());
|
||||
Assert.assertEquals(1, visitor.getConditions().size());
|
||||
|
||||
Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("haskell_function")));
|
||||
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("haskell_function", "arity")));
|
||||
Assert.assertTrue(visitor.getColumns().contains(new Column("haskell_function", "id")));
|
||||
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
Assert.assertEquals("UPDATE haskell_function"
|
||||
+ "\nSET `arity` = arity - '1'"
|
||||
+ "\nWHERE id = 1", //
|
||||
output);
|
||||
}
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
|
||||
Assert.assertEquals("update haskell_function"
|
||||
+ "\nset `arity` = arity - '1'"
|
||||
+ "\nwhere id = 1", //
|
||||
output);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.alibaba.druid.bvt.sql.schemaStat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SchemaStatTest4 extends TestCase {
|
||||
|
||||
public void test_schemaStat() throws Exception {
|
||||
String sql = "select name, age from t_user where id = 1";
|
||||
|
||||
String dbType = JdbcConstants.MYSQL;
|
||||
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
|
||||
SQLStatement stmt = stmtList.get(0);
|
||||
|
||||
SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(dbType);
|
||||
stmt.accept(statVisitor);
|
||||
|
||||
System.out.println(statVisitor.getColumns());
|
||||
System.out.println(statVisitor.getTables());
|
||||
System.out.println(statVisitor.getConditions());
|
||||
|
||||
Assert.assertEquals(3, statVisitor.getColumns().size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.alibaba.druid.bvt.sql.schemaStat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SchemaStatTest5 extends TestCase {
|
||||
|
||||
public void test_schemaStat() throws Exception {
|
||||
String sql = "create table t_org (fid int, name varchar(256))";
|
||||
|
||||
String dbType = JdbcConstants.MYSQL;
|
||||
List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
|
||||
SQLStatement stmt = stmtList.get(0);
|
||||
|
||||
SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(dbType);
|
||||
stmt.accept(statVisitor);
|
||||
|
||||
System.out.println(statVisitor.getColumns());
|
||||
System.out.println(statVisitor.getTables());
|
||||
System.out.println(statVisitor.getConditions());
|
||||
|
||||
Assert.assertEquals(2, statVisitor.getColumns().size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.alibaba.druid.bvt.sql.schemaStat;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class SchemaStatTest6 extends TestCase {
|
||||
public void test_schemaStat() throws Exception {
|
||||
String sql = "select count(1), name from tg_rpc_user where id < 5 group by name order by id desc";
|
||||
|
||||
|
||||
String dbType = JdbcConstants.MYSQL;
|
||||
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType);
|
||||
SQLStatement stmt = parser.parseStatementList().get(0);
|
||||
|
||||
SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(dbType);
|
||||
stmt.accept(statVisitor);
|
||||
|
||||
System.out.println(statVisitor.getColumns());
|
||||
System.out.println(statVisitor.getGroupByColumns()); // group by
|
||||
|
||||
Assert.assertEquals(2, statVisitor.getColumns().size());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.alibaba.druid.pool.postgres;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import com.alibaba.druid.pool.vendor.PGValidConnectionChecker;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* 这个场景测试minIdle > maxActive
|
||||
*
|
||||
* @author wenshao [szujobs@hotmail.com]
|
||||
*/
|
||||
public class PG_500_connection_Test extends TestCase {
|
||||
|
||||
private DruidDataSource dataSource;
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
dataSource = new DruidDataSource();
|
||||
dataSource.setUrl("jdbc:postgresql://192.168.199.231:5432/druid_test_db");
|
||||
dataSource.setUsername("druid_test");
|
||||
dataSource.setPassword("druid_test");
|
||||
dataSource.setInitialSize(50);
|
||||
dataSource.setMaxActive(80);
|
||||
dataSource.setMinIdle(50);
|
||||
dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10
|
||||
dataSource.setTimeBetweenEvictionRunsMillis(180 * 1000); // 180 / 10
|
||||
dataSource.setTestWhileIdle(false);
|
||||
dataSource.setTestOnBorrow(false);
|
||||
// dataSource.setValidationQuery("SELECT 1 FROM DUAL");
|
||||
dataSource.setFilters("stat");
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
dataSource.close();
|
||||
}
|
||||
|
||||
public void test_conect_500() throws Exception {
|
||||
dataSource.init();
|
||||
Assert.assertFalse(dataSource.isOracle());
|
||||
Assert.assertTrue(dataSource.getValidConnectionChecker() instanceof PGValidConnectionChecker);
|
||||
|
||||
int taskCount = 1000 * 100;
|
||||
final CountDownLatch endLatch = new CountDownLatch(taskCount);
|
||||
Runnable task = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Connection conn = null;
|
||||
Statement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
conn = dataSource.getConnection();
|
||||
stmt = conn.createStatement();
|
||||
rs = stmt.executeQuery("SELECT 1");
|
||||
while (rs.next()) {
|
||||
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
// skip
|
||||
} finally {
|
||||
endLatch.countDown();
|
||||
}
|
||||
JdbcUtils.close(rs);
|
||||
JdbcUtils.close(stmt);
|
||||
JdbcUtils.close(conn);
|
||||
}
|
||||
};
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(100);
|
||||
for (int i = 0; i < taskCount; ++i) {
|
||||
executor.submit(task);
|
||||
}
|
||||
endLatch.await();
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user