From 663a1c37ffb6ccff5c8c90a18c50149a77183650 Mon Sep 17 00:00:00 2001 From: Yako Date: Tue, 9 Sep 2014 20:04:50 +0800 Subject: [PATCH 1/3] improve sqlwall --- .../statement/SQLCreateDatabaseStatement.java | 19 ++++++++++++++--- .../ast/statement/SQLExplainStatement.java | 15 ++++++++++++- .../mysql/parser/MySqlStatementParser.java | 4 ++++ .../mysql/visitor/MySqlOutputVisitor.java | 21 ++++++------------- .../druid/sql/parser/SQLStatementParser.java | 7 ++++++- .../sql/visitor/SQLASTOutputVisitor.java | 12 ++++++----- .../bvt/filter/wall/MySqlWallTest_hint.java | 18 ++++++++++++++++ 7 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateDatabaseStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateDatabaseStatement.java index 2041161358..f0e4440559 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateDatabaseStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateDatabaseStatement.java @@ -15,16 +15,21 @@ */ package com.alibaba.druid.sql.ast.statement; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLCreateDatabaseStatement extends SQLStatementImpl { - private SQLName name; + private SQLName name; - private String characterSet; - private String collate; + private String characterSet; + private String collate; + + private List hints; public SQLCreateDatabaseStatement(){ } @@ -61,4 +66,12 @@ public class SQLCreateDatabaseStatement extends SQLStatementImpl { this.collate = collate; } + public List getHints() { + return hints; + } + + public void setHints(List hints) { + this.hints = hints; + } + } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainStatement.java index 1ffbbe6481..02a0bdee9d 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLExplainStatement.java @@ -15,13 +15,18 @@ */ package com.alibaba.druid.sql.ast.statement; +import java.util.List; + +import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLExplainStatement extends SQLStatementImpl { - protected SQLStatement statement; + protected SQLStatement statement; + + private List hints; public SQLStatement getStatement() { return statement; @@ -41,4 +46,12 @@ public class SQLExplainStatement extends SQLStatementImpl { } visitor.endVisit(this); } + + public List getHints() { + return hints; + } + + public void setHints(List hints) { + this.hints = hints; + } } 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 56b3f29809..a0d0f3d961 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 @@ -2537,6 +2537,10 @@ public class MySqlStatementParser extends SQLStatementParser { if (lexer.token() == Token.DEFAULT) { lexer.nextToken(); } + + if (lexer.token() == Token.HINT) { + stmt.setHints(this.exprParser.parseHints()); + } return stmt; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 4897da7bfb..1ae28929ea 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -1123,12 +1123,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(" WITH CONSISTENT SNAPSHOT"); } - List hints = x.getHints(); - if (hints != null && !hints.isEmpty()) { + if (x.getHints() != null && x.getHints().size() > 0) { print(" "); - for (SQLCommentHint hint : hints) { - hint.accept(this); - } + printAndAccept(x.getHints(), " "); } if (x.isBegin()) { @@ -2143,12 +2140,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV x.getTable().accept(this); } - List hints = x.getHints(); - if (hints != null && !hints.isEmpty()) { + if (x.getHints() != null && x.getHints().size() > 0) { print(" "); - for (SQLCommentHint hint : hints) { - hint.accept(this); - } + printAndAccept(x.getHints(), " "); } return false; @@ -2685,12 +2679,9 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(x.getLockType().name); } - List hints = x.getHints(); - if (hints != null && !hints.isEmpty()) { + if (x.getHints() != null && x.getHints().size() > 0) { print(" "); - for (SQLCommentHint hint : hints) { - hint.accept(this); - } + printAndAccept(x.getHints(), " "); } 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 93b2ded1f0..ccf68e08d4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -1534,8 +1534,13 @@ public class SQLStatementParser extends SQLParser { if (lexer.token() == Token.FOR) { lexer.nextToken(); } - + SQLExplainStatement explain = new SQLExplainStatement(); + + if(lexer.token == Token.HINT) { + explain.setHints(this.exprParser.parseHints()); + } + explain.setStatement(parseStatement()); return explain; diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 535a48c133..42f289b8c5 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1149,13 +1149,11 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print("SET "); printAndAccept(x.getItems(), ", "); - List hints = x.getHints(); - if (hints != null && !hints.isEmpty()) { + if (x.getHints() != null && x.getHints().size() > 0) { print(" "); - for (SQLCommentHint hint : hints) { - hint.accept(this); - } + printAndAccept(x.getHints(), " "); } + return false; } @@ -1770,6 +1768,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab @Override public boolean visit(SQLExplainStatement x) { print("EXPLAIN"); + if (x.getHints() != null && x.getHints().size() > 0) { + print(" "); + printAndAccept(x.getHints(), " "); + } println(); x.getStatement().accept(this); return false; diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest_hint.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest_hint.java index 48eb654b1a..02cc439e46 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest_hint.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest_hint.java @@ -110,4 +110,22 @@ public class MySqlWallTest_hint extends TestCase { + ") /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */ "; Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); // } + + public void test_true_10() throws Exception { + WallConfig config = new WallConfig(); + config.setHintAllow(true); + config.setMultiStatementAllow(true); + config.setNoneBaseStatementAllow(true); + String sql = "CREATE DATABASE `newsfocus` /*!40100 COLLATE 'big5_chinese_ci' */ "; + Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); // + } + + public void test_true_11() throws Exception { + WallConfig config = new WallConfig(); + config.setHintAllow(true); + config.setMultiStatementAllow(true); + config.setNoneBaseStatementAllow(true); + String sql = "EXPLAIN /*!40100 EXTENDED */ SELECT * FROM trade_order_header WHERE id = ?"; + Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); // + } } From 0f4af8e2a55875b5c6e61216faac8084202956f6 Mon Sep 17 00:00:00 2001 From: Yako Date: Thu, 18 Sep 2014 16:08:46 +0800 Subject: [PATCH 2/3] bugfix for SQLServerParameterizedOutputVisitor hex --- .../visitor/SQLServerParameterizedOutputVisitor.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java index 74a75774bc..e282617ce6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerParameterizedOutputVisitor.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLHexExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; @@ -99,5 +100,13 @@ public class SQLServerParameterizedOutputVisitor extends SQLServerOutputVisitor return ParameterizedOutputVisitorUtils.visit(this, x); } + + public boolean visit(SQLHexExpr x) { + if (!ParameterizedOutputVisitorUtils.checkParameterize(x)) { + return super.visit(x); + } + + return ParameterizedOutputVisitorUtils.visit(this, x); + } } From 4ae4bbfd0bf3b56a8893d5f9b653243eda2cb79d Mon Sep 17 00:00:00 2001 From: Yako Date: Mon, 22 Sep 2014 11:19:03 +0800 Subject: [PATCH 3/3] improve sqlserver parser --- .../ast/stmt/SQLServerSetStatement.java | 56 ++++++++ ...SetTransactionIsolationLevelStatement.java | 40 ++++++ .../parser/SQLServerStatementParser.java | 90 +++++++++++++ .../visitor/SQLServerASTVisitor.java | 9 ++ .../visitor/SQLServerASTVisitorAdapter.java | 22 ++++ .../visitor/SQLServerOutputVisitor.java | 30 +++++ .../visitor/SQLServerSchemaStatVisitor.java | 22 ++++ .../bvt/sql/sqlserver/SQLServerSetTest.java | 120 ++++++++++++++++++ 8 files changed, 389 insertions(+) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetTransactionIsolationLevelStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSetTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetStatement.java new file mode 100644 index 0000000000..3bf15a6957 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetStatement.java @@ -0,0 +1,56 @@ +/* + * 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.sql.dialect.sqlserver.ast.stmt; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; + +public class SQLServerSetStatement extends SQLServerObjectImpl implements SQLServerStatement { + + private SQLAssignItem item = new SQLAssignItem(); + + + public SQLServerSetStatement(){ + } + + public SQLServerSetStatement(SQLExpr target, SQLExpr value){ + this.item = new SQLAssignItem(target, value); + } + + public SQLAssignItem getItem() { + return item; + } + + public void setItem(SQLAssignItem item) { + this.item = item; + } + + public void output(StringBuffer buf) { + buf.append("SET "); + item.output(buf); + } + + @Override + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.item); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetTransactionIsolationLevelStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetTransactionIsolationLevelStatement.java new file mode 100644 index 0000000000..558467357e --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerSetTransactionIsolationLevelStatement.java @@ -0,0 +1,40 @@ +/* + * 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.sql.dialect.sqlserver.ast.stmt; + +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; + +public class SQLServerSetTransactionIsolationLevelStatement extends SQLServerObjectImpl implements SQLServerStatement { + + private String level; + + @Override + public void accept0(SQLServerASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index ab0fc58e10..f279bf2da5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -19,16 +19,21 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; @@ -181,4 +186,89 @@ public class SQLServerStatementParser extends SQLStatementParser { public SQLServerExprParser getExprParser() { return (SQLServerExprParser) exprParser; } + + public SQLStatement parseSet() { + accept(Token.SET); + + if (identifierEquals("TRANSACTION")) { + lexer.nextToken(); + acceptIdentifier("ISOLATION"); + acceptIdentifier("LEVEL"); + + SQLServerSetTransactionIsolationLevelStatement stmt = new SQLServerSetTransactionIsolationLevelStatement(); + + if (identifierEquals("READ")) { + lexer.nextToken(); + + if (identifierEquals("UNCOMMITTED")) { + stmt.setLevel("READ UNCOMMITTED"); + lexer.nextToken(); + } else if (identifierEquals("COMMITTED")) { + stmt.setLevel("READ COMMITTED"); + lexer.nextToken(); + } else { + throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal()); + } + } else if (identifierEquals("SERIALIZABLE")) { + stmt.setLevel("SERIALIZABLE"); + lexer.nextToken(); + } else if (identifierEquals("SNAPSHOT")) { + stmt.setLevel("SNAPSHOT"); + lexer.nextToken(); + } else if (identifierEquals("REPEATABLE")) { + lexer.nextToken(); + if (identifierEquals("READ")) { + stmt.setLevel("REPEATABLE READ"); + lexer.nextToken(); + } else { + throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal()); + } + } else { + throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal()); + } + + return stmt; + } + + if (identifierEquals("STATISTICS")) { + lexer.nextToken(); + + SQLServerSetStatement stmt = new SQLServerSetStatement(); + + if (identifierEquals("IO") || identifierEquals("XML") || identifierEquals("PROFILE") + || identifierEquals("TIME")) { + stmt.getItem().setTarget(new SQLIdentifierExpr("STATISTICS " + lexer.stringVal().toUpperCase())); + + lexer.nextToken(); + if (lexer.token() == Token.ON) { + stmt.getItem().setValue(new SQLIdentifierExpr("ON")); + lexer.nextToken(); + } else if (identifierEquals("OFF")) { + stmt.getItem().setValue(new SQLIdentifierExpr("OFF")); + lexer.nextToken(); + } + } + return stmt; + } + + if (lexer.token() == Token.VARIANT) { + SQLSetStatement stmt = new SQLSetStatement(); + parseAssignItems(stmt.getItems(), stmt); + return stmt; + } else { + SQLServerSetStatement stmt = new SQLServerSetStatement(); + stmt.getItem().setTarget(this.exprParser.expr()); + + if (lexer.token() == Token.ON) { + stmt.getItem().setValue(new SQLIdentifierExpr("ON")); + lexer.nextToken(); + } else if (identifierEquals("OFF")) { + stmt.getItem().setValue(new SQLIdentifierExpr("OFF")); + lexer.nextToken(); + } else { + stmt.getItem().setValue(this.exprParser.expr()); + } + return stmt; + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java index e328581ae6..c4a9b7a04a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java @@ -21,6 +21,8 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -58,4 +60,11 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { void endVisit(SQLServerExecStatement x); + boolean visit(SQLServerSetTransactionIsolationLevelStatement x); + + void endVisit(SQLServerSetTransactionIsolationLevelStatement x); + + boolean visit(SQLServerSetStatement x); + + void endVisit(SQLServerSetStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java index 6f8a5997b9..6f610afe12 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -21,6 +21,8 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; @@ -106,4 +108,24 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(SQLServerSetTransactionIsolationLevelStatement x) { + return true; + } + + @Override + public void endVisit(SQLServerSetTransactionIsolationLevelStatement x) { + + } + + @Override + public boolean visit(SQLServerSetStatement x) { + return true; + } + + @Override + public void endVisit(SQLServerSetStatement x) { + + } + } 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 6bb20d8fbb..5f31ac1df4 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 @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLSetQuantifier; +import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; @@ -27,6 +28,8 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -320,4 +323,31 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe public void endVisit(SQLServerExecStatement x) { } + + @Override + public boolean visit(SQLServerSetTransactionIsolationLevelStatement x) { + print("SET TRANSACTION ISOLATION LEVEL "); + print(x.getLevel()); + return false; + } + + @Override + public void endVisit(SQLServerSetTransactionIsolationLevelStatement x) { + + } + + @Override + public boolean visit(SQLServerSetStatement x) { + print("SET "); + SQLAssignItem item = x.getItem(); + item.getTarget().accept(this); + print(" "); + item.getValue().accept(this); + return false; + } + + @Override + public void endVisit(SQLServerSetStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index d4e1236280..a086de6e5f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -27,6 +27,8 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; @@ -135,4 +137,24 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL } + @Override + public boolean visit(SQLServerSetTransactionIsolationLevelStatement x) { + return false; + } + + @Override + public void endVisit(SQLServerSetTransactionIsolationLevelStatement x) { + + } + + @Override + public boolean visit(SQLServerSetStatement x) { + return false; + } + + @Override + public void endVisit(SQLServerSetStatement x) { + + } + } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSetTest.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSetTest.java new file mode 100644 index 0000000000..6ba7934302 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSetTest.java @@ -0,0 +1,120 @@ +/* + * 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 java.util.List; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.util.JdbcUtils; + +public class SQLServerSetTest extends TestCase { + + public void test_0() { + String sql = "SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List stmtList = parser.parseStatementList(); + SQLStatement stmt = stmtList.get(0); + + Assert.assertEquals(1, stmtList.size()); + + SQLServerSchemaStatVisitor visitor = new SQLServerSchemaStatVisitor(); + 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(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + String text = SQLUtils.toSQLString(stmtList, JdbcUtils.SQL_SERVER); + + Assert.assertEquals("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED", text); + } + + public void test_1() { + String sql = "SET FMTONLY ON"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List stmtList = parser.parseStatementList(); + SQLStatement stmt = stmtList.get(0); + + Assert.assertEquals(1, stmtList.size()); + + SQLServerSchemaStatVisitor visitor = new SQLServerSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + String text = SQLUtils.toSQLString(stmtList, JdbcUtils.SQL_SERVER); + + Assert.assertEquals("SET FMTONLY ON", text); + } + + public void test_2() { + String sql = "SET STATISTICS XML OFF"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List stmtList = parser.parseStatementList(); + SQLStatement stmt = stmtList.get(0); + + Assert.assertEquals(1, stmtList.size()); + + SQLServerSchemaStatVisitor visitor = new SQLServerSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + String text = SQLUtils.toSQLString(stmtList, JdbcUtils.SQL_SERVER); + + Assert.assertEquals("SET STATISTICS XML OFF", text); + } + + public void test_3() { + String sql = "SET @state = N'Oregon'"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List stmtList = parser.parseStatementList(); + SQLStatement stmt = stmtList.get(0); + + Assert.assertEquals(1, stmtList.size()); + + SQLServerSchemaStatVisitor visitor = new SQLServerSchemaStatVisitor(); + stmt.accept(visitor); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + String text = SQLUtils.toSQLString(stmtList, JdbcUtils.SQL_SERVER); + + Assert.assertEquals("SET @state = N'Oregon'", text); + } +}