improve sqlwall: 'hints' and 'start transaction'

This commit is contained in:
Yako
2014-09-03 16:31:37 +08:00
parent 3d8031552a
commit 9b58d41f69
11 changed files with 137 additions and 7 deletions
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.ast.statement;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatementImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -25,6 +26,8 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLSetStatement extends SQLStatementImpl {
private List<SQLAssignItem> items = new ArrayList<SQLAssignItem>();
private List<SQLCommentHint> hints;
public SQLSetStatement(){
}
@@ -41,10 +44,19 @@ public class SQLSetStatement extends SQLStatementImpl {
this.items = items;
}
public List<SQLCommentHint> getHints() {
return hints;
}
public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.items);
acceptChild(visitor, this.hints);
}
visitor.endVisit(this);
}
@@ -15,6 +15,9 @@
*/
package com.alibaba.druid.sql.dialect.mysql.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.statement.SQLExprTableSource;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
@@ -24,6 +27,8 @@ public class MySqlLockTableStatement extends MySqlStatementImpl {
private SQLExprTableSource tableSource;
private LockType lockType;
private List<SQLCommentHint> hints;
public SQLExprTableSource getTableSource() {
return tableSource;
@@ -64,4 +69,12 @@ public class MySqlLockTableStatement extends MySqlStatementImpl {
this.name = name;
}
}
public List<SQLCommentHint> getHints() {
return hints;
}
public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}
}
@@ -15,6 +15,9 @@
*/
package com.alibaba.druid.sql.dialect.mysql.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.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
@@ -22,8 +25,9 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlShowIndexesStatement extends MySqlStatementImpl implements MySqlShowStatement {
private SQLName table;
private SQLName database;
private SQLName table;
private SQLName database;
private List<SQLCommentHint> hints;
public SQLName getTable() {
return table;
@@ -54,4 +58,12 @@ public class MySqlShowIndexesStatement extends MySqlStatementImpl implements MyS
}
visitor.endVisit(this);
}
public List<SQLCommentHint> getHints() {
return hints;
}
public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}
}
@@ -15,14 +15,19 @@
*/
package com.alibaba.druid.sql.dialect.mysql.ast.statement;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlStartTransactionStatement extends MySqlStatementImpl {
private boolean consistentSnapshot = false;
private boolean consistentSnapshot = false;
private boolean begin = false;
private boolean work = false;
private boolean begin = false;
private boolean work = false;
private List<SQLCommentHint> hints;
public boolean isConsistentSnapshot() {
return consistentSnapshot;
@@ -53,4 +58,12 @@ public class MySqlStartTransactionStatement extends MySqlStatementImpl {
visitor.endVisit(this);
}
public List<SQLCommentHint> getHints() {
return hints;
}
public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}
}
@@ -654,6 +654,9 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.setLockType(LockType.LOW_PRIORITY_WRITE);
}
if(lexer.token() == Token.HINT) {
stmt.setHints(this.exprParser.parseHints());
}
statementList.add(stmt);
return true;
}
@@ -1101,6 +1104,10 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.setDatabase(database);
}
}
if (lexer.token() == Token.HINT) {
stmt.setHints(this.exprParser.parseHints());
}
return stmt;
}
@@ -1492,6 +1499,10 @@ public class MySqlStatementParser extends SQLStatementParser {
stmt.setWork(true);
}
}
if(lexer.token() == Token.HINT) {
stmt.setHints(this.exprParser.parseHints());
}
return stmt;
}
@@ -2123,6 +2134,10 @@ public class MySqlStatementParser extends SQLStatementParser {
SQLVariantRefExpr varRef = (SQLVariantRefExpr) stmt.getItems().get(0).getTarget();
varRef.setGlobal(true);
}
if(lexer.token() == Token.HINT) {
stmt.setHints(this.exprParser.parseHints());
}
return stmt;
}
@@ -1118,6 +1118,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
if (x.isConsistentSnapshot()) {
print(" WITH CONSISTENT SNAPSHOT");
}
List<SQLCommentHint> hints = x.getHints();
if (hints != null && !hints.isEmpty()) {
print(" ");
for (SQLCommentHint hint : hints) {
hint.accept(this);
}
}
if (x.isBegin()) {
print(" BEGIN");
@@ -2130,6 +2138,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
x.getTable().accept(this);
}
List<SQLCommentHint> hints = x.getHints();
if (hints != null && !hints.isEmpty()) {
print(" ");
for (SQLCommentHint hint : hints) {
hint.accept(this);
}
}
return false;
}
@@ -2664,6 +2680,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print(' ');
print(x.getLockType().name);
}
List<SQLCommentHint> hints = x.getHints();
if (hints != null && !hints.isEmpty()) {
print(" ");
for (SQLCommentHint hint : hints) {
hint.accept(this);
}
}
return false;
}
@@ -1148,6 +1148,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
public boolean visit(SQLSetStatement x) {
print("SET ");
printAndAccept(x.getItems(), ", ");
List<SQLCommentHint> hints = x.getHints();
if (hints != null && !hints.isEmpty()) {
print(" ");
for (SQLCommentHint hint : hints) {
hint.accept(this);
}
}
return false;
}
@@ -42,6 +42,7 @@ public class WallConfig implements WallConfigMBean {
private boolean renameTableAllow = true;
private boolean hintAllow = true;
private boolean lockTableAllow = true;
private boolean startTransactionAllow = true;
private boolean conditionAndAlwayTrueAllow = false;
private boolean conditionAndAlwayFalseAllow = false;
@@ -761,4 +762,12 @@ public class WallConfig implements WallConfigMBean {
this.lockTableAllow = lockTableAllow;
}
public boolean isStartTransactionAllow() {
return startTransactionAllow;
}
public void setStartTransactionAllow(boolean startTransactionAllow) {
this.startTransactionAllow = startTransactionAllow;
}
}
@@ -107,6 +107,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatemen
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowGrantsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSequenceStatement;
@@ -2416,6 +2417,10 @@ public class WallVisitorUtils {
allow = config.isLockTableAllow();
denyMessage = "lock table not allow";
errorCode = ErrorCode.LOCK_TABLE_NOT_ALLOW;
} else if (x instanceof MySqlStartTransactionStatement) {
allow = config.isStartTransactionAllow();
denyMessage = "start transaction not allow";
errorCode = ErrorCode.START_TRANSACTION_NOT_ALLOW;
} else {
allow = config.isNoneBaseStatementAllow();
errorCode = ErrorCode.NONE_BASE_STATEMENT_NOT_ALLOW;
@@ -33,6 +33,7 @@ public interface ErrorCode {
public final static int CALL_NOT_ALLOW = 1300;
public final static int COMMIT_NOT_ALLOW = 1301;
public final static int ROLLBACK_NOT_ALLOW = 1302;
public final static int START_TRANSACTION_NOT_ALLOW = 1303;
public final static int SET_NOT_ALLOW = 1200;
public final static int DESC_NOT_ALLOW = 1201;
@@ -47,7 +48,7 @@ public interface ErrorCode {
public final static int DROP_TABLE_NOT_ALLOW = 1103;
public final static int COMMENT_STATEMENT_NOT_ALLOW = 1104;
public final static int RENAME_TABLE_NOT_ALLOW = 1105;
public final static int LOCK_TABLE_NOT_ALLOW = 1105;
public final static int LOCK_TABLE_NOT_ALLOW = 1106;
public final static int LIMIT_ZERO = 2200;
public final static int MULTI_STATEMENT = 2201;
@@ -17,8 +17,11 @@ public class MySqlWallTest_hint extends TestCase {
}
public void test_false_1() throws Exception {
WallConfig config = new WallConfig();
config.setHintAllow(true);
config.setMultiStatementAllow(true);
String sql = "select * from person where id = '3'/**/union select 0,1,v from (select 1,2,user/*!() as v*/) a where '1'<>''";
Assert.assertFalse(WallUtils.isValidateMySql(sql)); //
Assert.assertFalse(WallUtils.isValidateMySql(sql, config)); //
}
public void test_true() throws Exception {
@@ -77,4 +80,19 @@ public class MySqlWallTest_hint extends TestCase {
Assert.assertTrue(WallUtils.isValidateMySql(sql, config)); //
}
public void test_true_6() throws Exception {
String sql = "START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
public void test_true_7() throws Exception {
String sql = "LOCK TABLES `m_rpt_adgroupeffect` READ /*!32311 LOCAL */";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
public void test_true_8() throws Exception {
String sql = "SET SQL_QUOTE_SHOW_CREATE=1/*!40102 ,SQL_MODE=concat(@@sql_mode, _utf8 ',NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS') */";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
}