improve sqlwall for mysql hints

This commit is contained in:
Yako
2014-08-29 15:16:29 +08:00
parent c74754dfd4
commit 0e200b491c
4 changed files with 82 additions and 56 deletions
@@ -448,7 +448,7 @@ public class MySqlLexer extends Lexer {
return;
}
if (!isAllowComment() && (isEOF() || !isSafeComment(stringVal))) {
if (!isHint && !isAllowComment() && (isEOF() || !isSafeComment(stringVal))) {
throw new NotAllowCommentException();
}
@@ -15,21 +15,7 @@
*/
package com.alibaba.druid.wall;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.NotAllowCommentException;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
import com.alibaba.druid.util.LRUCache;
import com.alibaba.druid.util.Utils;
import com.alibaba.druid.wall.spi.WallVisitorUtils;
import com.alibaba.druid.wall.violation.ErrorCode;
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
import com.alibaba.druid.wall.violation.SyntaxErrorViolation;
import static com.alibaba.druid.util.JdbcSqlStatUtils.get;
import java.security.PrivilegedAction;
import java.util.ArrayList;
@@ -44,7 +30,22 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static com.alibaba.druid.util.JdbcSqlStatUtils.get;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlHintStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.NotAllowCommentException;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
import com.alibaba.druid.util.LRUCache;
import com.alibaba.druid.util.Utils;
import com.alibaba.druid.wall.spi.WallVisitorUtils;
import com.alibaba.druid.wall.violation.ErrorCode;
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
import com.alibaba.druid.wall.violation.SyntaxErrorViolation;
public abstract class WallProvider {
@@ -640,7 +641,13 @@ public abstract class WallProvider {
WallVisitor visitor = createWallVisitor();
if (statementList.size() > 0) {
for (SQLStatement stmt : statementList) {
boolean lastIsHint = false;
for (int i=0; i<statementList.size(); i++) {
SQLStatement stmt = statementList.get(i);
if ((i == 0 || lastIsHint) && stmt instanceof MySqlHintStatement) {
lastIsHint = true;
continue;
}
try {
stmt.accept(visitor);
} catch (ParserException e) {
@@ -653,16 +660,6 @@ public abstract class WallProvider {
violations.addAll(visitor.getViolations());
}
// if (visitor.getViolations().size() == 0 && context != null && context.getWarnings() >= 2) {
// if (context.getCommentCount() > 0) {
// violations.add(new IllegalSQLObjectViolation(ErrorCode.COMMIT_NOT_ALLOW, "comment not allow", sql));
// } else if (context.getLikeNumberWarnings() > 0) {
// violations.add(new IllegalSQLObjectViolation(ErrorCode.COMMIT_NOT_ALLOW, "like number", sql));
// } else {
// violations.add(new IllegalSQLObjectViolation(ErrorCode.COMPOUND, "multi-warnnings", sql));
// }
// }
WallSqlStat sqlStat = null;
if (violations.size() > 0) {
violationCount.incrementAndGet();
@@ -1,28 +0,0 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallUtils;
public class HintTest extends TestCase {
public void test_false() throws Exception {
WallConfig config = new WallConfig();
config.setHintAllow(false);
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, config)); //
}
public void test_false_1() throws Exception {
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)); //
}
public void test_true() throws Exception {
String sql = "SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
}
@@ -0,0 +1,57 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.TestCase;
import org.junit.Assert;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallUtils;
public class MySqlWallTest_hint extends TestCase {
public void test_false() throws Exception {
WallConfig config = new WallConfig();
config.setHintAllow(false);
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, config)); //
}
public void test_false_1() throws Exception {
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)); //
}
public void test_true() throws Exception {
String sql = "SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
public void test_true_1() throws Exception {
String sql = "/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
public void test_true_2() throws Exception {
String sql = "/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */";
Assert.assertTrue(WallUtils.isValidateMySql(sql)); //
}
public void test_true_3() throws Exception {
WallConfig config = new WallConfig();
config.setHintAllow(true);
config.setMultiStatementAllow(true);
String sql = " /*!50003 CREATE*/ /*!50020 /*!50003 PROCEDURE `top_calculate_customer_update`(in update_time DATETIME)"
+ " DETERMINISTIC"
+ " BEGIN"
+ " DECLARE done INT DEFAULT FALSE;"
+ " DECLARE c_receiver_city,c_receiver_district,c_receiver_address VARCHAR(200);"
+ " DECLARE c_last_updated DATETIME;"
+ " DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;"
+ " insert into top_calculate_customer_log (execute_time,info) values (now(),'update table top_taobao_order_customer_mid begin');"
+ " update top_tmp_order_middle_last_sync set status = 'wait', last_sync = update_time where plat_form = 'taobao' and status = 'blocking';"
+ " END */";
Assert.assertTrue(WallUtils.isValidateMySql(sql, config));
}
}