diff --git a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java index e99ecb205d..d4d8bed89e 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java +++ b/src/main/java/com/alibaba/druid/pool/DruidPooledConnection.java @@ -53,25 +53,27 @@ import com.alibaba.druid.support.logging.LogFactory; */ public class DruidPooledConnection extends PoolableWrapper implements javax.sql.PooledConnection, Connection { - private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class); + private final static Log LOG = LogFactory.getLog(DruidPooledConnection.class); + + public static final int MAX_RECORD_SQL_COUNT = 10; protected Connection conn; protected volatile DruidConnectionHolder holder; protected TransactionInfo transactionInfo; private final boolean dupCloseLogEnable; - private volatile boolean traceEnable = false; - private boolean disable = false; - private boolean closed = false; + private volatile boolean traceEnable = false; + private boolean disable = false; + private boolean closed = false; private final Thread ownerThread; private long connectedTimeNano; - private volatile boolean running = false; + private volatile boolean running = false; - private volatile boolean abandoned = false; + private volatile boolean abandoned = false; private StackTraceElement[] connectStackTrace; - private Throwable disableError = null; + private Throwable disableError = null; public DruidPooledConnection(DruidConnectionHolder holder){ super(holder.getConnection()); @@ -686,7 +688,10 @@ public class DruidPooledConnection extends PoolableWrapper implements javax.sql. } if (transactionInfo != null) { - transactionInfo.getSqlList().add(sql); + List sqlList = transactionInfo.getSqlList(); + if (sqlList.size() < MAX_RECORD_SQL_COUNT) { + sqlList.add(sql); + } } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java index 6e1c20beb9..b363021e90 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateViewStatement.java @@ -26,6 +26,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLStatement { private static final long serialVersionUID = 1L; + private boolean orReplace = false; protected SQLName name; protected SQLSelect subQuery; @@ -37,6 +38,14 @@ public class SQLCreateViewStatement extends SQLStatementImpl implements SQLDDLSt } + public boolean isOrReplace() { + return orReplace; + } + + public void setOrReplace(boolean orReplace) { + this.orReplace = orReplace; + } + public SQLName getName() { return name; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 6745d627ab..2570a9e325 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -284,11 +284,24 @@ public class MySqlStatementParser extends SQLStatementParser { } public SQLStatement parseCreate() { + char markChar = lexer.current(); + int markBp = lexer.bp(); + accept(Token.CREATE); + boolean replace = false; + if (lexer.token() == Token.OR) { + lexer.nextToken(); + acceptIdentifier("REPLACE"); + replace = true; + } + List hints = this.exprParser.parseHints(); if (lexer.token() == Token.TABLE || identifierEquals(TEMPORARY)) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } MySqlCreateTableParser parser = new MySqlCreateTableParser(this.exprParser); MySqlCreateTableStatement stmt = parser.parseCrateTable(false); stmt.setHints(hints); @@ -296,19 +309,32 @@ public class MySqlStatementParser extends SQLStatementParser { } if (lexer.token() == Token.DATABASE) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } return parseCreateDatabase(); } if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || identifierEquals(FULLTEXT) || identifierEquals(SPATIAL)) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } return parseCreateIndex(); } if (identifierEquals(USER)) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } return parseCreateUser(); } - + if (lexer.token() == Token.VIEW) { + if (replace) { + lexer.reset(markBp, markChar, Token.CREATE); + } + return parseCreateView(); } @@ -1494,7 +1520,7 @@ public class MySqlStatementParser extends SQLStatementParser { if (lexer.token() == Token.VALUES || identifierEquals("VALUE")) { lexer.nextToken(); - + parseValueClause(stmt.getValuesList(), 0); } else if (lexer.token() == Token.SELECT) { SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); @@ -1871,7 +1897,7 @@ public class MySqlStatementParser extends SQLStatementParser { } } } - + SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause(valueExprList); valueClauseList.add(values); } else { @@ -2222,11 +2248,11 @@ public class MySqlStatementParser extends SQLStatementParser { if (identifierEquals("COLUMN")) { lexer.nextToken(); } - + SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn(); SQLColumnDefinition columnDef = this.exprParser.parseColumn(); alterColumn.setColumn(columnDef); - + stmt.getItems().add(alterColumn); } else if (identifierEquals("CHANGE")) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index f1295d383f..a4a33559d1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -1078,6 +1078,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlDropViewStatement x) { + setMode(x, Mode.Drop); return true; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java index 6d2a348af4..e9d8cc3838 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -129,6 +129,11 @@ public class SQLServerExprParser extends SQLExprParser { accept(Token.RPAREN); } + if (lexer.token() == Token.PERCENT) { + lexer.nextToken(); + top.setPercent(true); + } + return top; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index 676440b361..d1b5e5f9a0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -39,6 +39,7 @@ public class SQLServerLexer extends Lexer { map.put("TOP", Token.TOP); map.put("USE", Token.USE); map.put("WITH", Token.WITH); + map.put("PERCENT", Token.PERCENT); DEFAULT_SQL_SERVER_KEYWORDS = new Keywords(map); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java index 9cedc21efd..ee69d85354 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java @@ -76,9 +76,7 @@ public class SQLServerSelectParser extends SQLSelectParser { } if (lexer.token() == Token.TOP) { - SQLServerTop top = new SQLServerTop(); - lexer.nextToken(); - top.setExpr(createExprParser().primary()); + SQLServerTop top = this.createExprParser().parseTop(); queryBlock.setTop(top); } @@ -101,7 +99,7 @@ public class SQLServerSelectParser extends SQLSelectParser { return queryRest(queryBlock); } - protected SQLExprParser createExprParser() { + protected SQLServerExprParser createExprParser() { return new SQLServerExprParser(lexer); } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index 1b81b38ff6..8f49ef7198 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -96,6 +96,10 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe print(")"); } + if (x.isPercent()) { + print(" PERCENT"); + } + return false; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 7e03f8a6b1..d34bee1e6d 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -644,6 +644,12 @@ public class SQLStatementParser extends SQLParser { if (lexer.token() == Token.CREATE) { lexer.nextToken(); } + + if (lexer.token() == Token.OR) { + lexer.nextToken(); + acceptIdentifier("REPLACE"); + createView.setOrReplace(true); + } this.accept(Token.VIEW); 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 57bca5f812..23ace595ee 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -808,6 +808,9 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { case Merge: stat.incrementMergeCount(); break; + case Drop: + stat.incrementDropCount(); + break; default: break; } diff --git a/src/main/java/com/alibaba/druid/stat/TableStat.java b/src/main/java/com/alibaba/druid/stat/TableStat.java index ed5c748f1d..f52d0f06ef 100644 --- a/src/main/java/com/alibaba/druid/stat/TableStat.java +++ b/src/main/java/com/alibaba/druid/stat/TableStat.java @@ -445,7 +445,14 @@ public class TableStat { } public static enum Mode { - Insert(1), Update(2), Delete(4), Select(8), Merge(16), Truncate(32), Alter(64); + Insert(1), // + Update(2), // + Delete(4), // + Select(8), // + Merge(16), // + Truncate(32), // + Alter(64), // + Drop(128); public final int mark; diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java index 94de69496e..a78baa0ee3 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java @@ -21,7 +21,7 @@ import junit.framework.Assert; import com.alibaba.druid.sql.MysqlTest; import com.alibaba.druid.sql.ast.SQLStatement; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; import com.alibaba.druid.stat.TableStat; @@ -30,14 +30,14 @@ import com.alibaba.druid.stat.TableStat.Column; public class MySqlCreateTableTest9 extends MysqlTest { public void test_0() throws Exception { - String sql = "CREATE VIEW view AS\n" + // + String sql = "CREATE VIEW v AS\n" + // "SELECT ProductID,ProductName\n" + // "FROM Products\n" + // "WHERE Discontinued=No"; MySqlStatementParser parser = new MySqlStatementParser(sql); List statementList = parser.parseStatementList(); - MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0); + SQLCreateViewStatement stmt = (SQLCreateViewStatement) statementList.get(0); print(statementList); Assert.assertEquals(1, statementList.size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateViewTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateViewTest.java new file mode 100644 index 0000000000..39913dd643 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateViewTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2011 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 junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; +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 MySqlCreateViewTest extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE OR REPLACE VIEW view_name AS\n" + // + "SELECT fname\n" + // + "FROM table_name\n" + // + "WHERE fid = ?"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLCreateViewStatement stmt = (SQLCreateViewStatement) 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("table_name"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("table_name", "fid"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("table_name", "fname"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDropViewTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDropViewTest.java new file mode 100644 index 0000000000..06f2a96e49 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDropViewTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2011 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 junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropViewStatement; +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 MySqlDropViewTest extends MysqlTest { + + public void test_0() throws Exception { + String sql = "DROP VIEW view_name"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + MySqlDropViewStatement stmt = (MySqlDropViewStatement) 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(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("view_name"))); + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest15.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest15.java new file mode 100644 index 0000000000..e52b3b28f1 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest15.java @@ -0,0 +1,43 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerSelectTest15 extends TestCase { + + public void test_simple() throws Exception { + String sql = "SELECT TOP 50 PERCENT * FROM Persons"; // + + String expect = "SELECT TOP 50 PERCENT *\n" + // + "FROM Persons"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +}