From fb5ef78a72f04d3f33ec19397e57516956c1679b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Thu, 15 Mar 2012 21:06:59 +0800 Subject: [PATCH] add sql wall support --- .../wall/IllegalConditionViolation.java | 4 + .../wall/IllegalSQLObjectViolation.java | 16 ++- .../alibaba/druid/filter/wall/Violation.java | 2 +- .../druid/filter/wall/WallProvider.java | 1 + .../filter/wall/spi/MySqlWallVisitor.java | 47 ++++++- .../mysql/ast/expr/MySqlOutFileExpr.java | 111 ++++++++++++++++ .../ast/statement/MySqlSelectQueryBlock.java | 119 +++--------------- .../dialect/mysql/parser/MySqlExprParser.java | 10 ++ .../mysql/parser/MySqlSelectParser.java | 20 +-- .../mysql/visitor/MySqlASTVisitor.java | 5 + .../mysql/visitor/MySqlASTVisitorAdapter.java | 11 ++ .../mysql/visitor/MySqlOutputVisitor.java | 101 ++++++++------- .../mysql/visitor/MySqlSchemaStatVisitor.java | 11 ++ .../druid/sql/parser/SQLSelectParser.java | 4 - .../druid/bvt/filter/wall/MySqlWallTest.java | 11 ++ 15 files changed, 307 insertions(+), 166 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOutFileExpr.java diff --git a/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java b/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java index c9477e6ca2..e35e686fed 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java +++ b/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java @@ -19,5 +19,9 @@ public class IllegalConditionViolation implements Violation { public void setCondition(String condition) { this.condition = condition; } + + public String toString() { + return this.condition; + } } diff --git a/src/main/java/com/alibaba/druid/filter/wall/IllegalSQLObjectViolation.java b/src/main/java/com/alibaba/druid/filter/wall/IllegalSQLObjectViolation.java index 14ff196e4d..9a2635150b 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/IllegalSQLObjectViolation.java +++ b/src/main/java/com/alibaba/druid/filter/wall/IllegalSQLObjectViolation.java @@ -2,22 +2,26 @@ package com.alibaba.druid.filter.wall; public class IllegalSQLObjectViolation implements Violation { - private String condition; + private String sqlPart; public IllegalSQLObjectViolation(){ } public IllegalSQLObjectViolation(String condition){ - this.condition = condition; + this.sqlPart = condition; } - public String getCondition() { - return condition; + public String getSqlPart() { + return sqlPart; } - public void setCondition(String condition) { - this.condition = condition; + public void setSqlPart(String sqlPart) { + this.sqlPart = sqlPart; + } + + public String toString() { + return this.sqlPart; } } diff --git a/src/main/java/com/alibaba/druid/filter/wall/Violation.java b/src/main/java/com/alibaba/druid/filter/wall/Violation.java index d9b6192f23..a1c19421ef 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/Violation.java +++ b/src/main/java/com/alibaba/druid/filter/wall/Violation.java @@ -1,6 +1,6 @@ package com.alibaba.druid.filter.wall; - public interface Violation { + String toString(); } diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java b/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java index 90030ec8c5..650eaf8f1f 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallProvider.java @@ -64,6 +64,7 @@ public abstract class WallProvider { if (visitor.getViolations().size() > 0) { if (throwException) { + visitor.getViolations().get(0); throw new WallRuntimeException(); } else { return false; diff --git a/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java index 285cab69ff..bce63784ac 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/filter/wall/spi/MySqlWallVisitor.java @@ -17,7 +17,10 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement; @@ -27,8 +30,9 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisitor { - private Set permitFunctions = new HashSet(); - private Set permitSchemas = new HashSet(); + private Set permitFunctions = new HashSet(); + private Set permitTablesoures = new HashSet(); + private Set permitSchemas = new HashSet(); private final List violations; @@ -39,9 +43,21 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi public MySqlWallVisitor(List violations){ this.violations = violations; -permitFunctions.add("load_file"); + permitFunctions.add("version"); + permitFunctions.add("load_file"); + permitFunctions.add("databse"); + permitFunctions.add("schema"); + permitFunctions.add("user"); + permitFunctions.add("system_user"); + permitFunctions.add("session_user"); + permitFunctions.add("benchmark"); + permitFunctions.add("connection_id"); + permitFunctions.add("current_user"); -permitSchemas.add("information_schema"); + permitSchemas.add("information_schema"); + permitSchemas.add("mysql"); + + permitTablesoures.add("outfile"); } public List getViolations() { @@ -137,4 +153,27 @@ permitSchemas.add("information_schema"); return true; } + + @Override + public boolean visit(MySqlOutFileExpr x) { + violations.add(new IllegalSQLObjectViolation(SQLUtils.toMySqlString(x))); + return false; + } + + @Override + public boolean visit(SQLUnionQuery x) { + if (queryBlockFromIsNull(x.getLeft()) || queryBlockFromIsNull(x.getRight())) { + violations.add(new IllegalSQLObjectViolation(SQLUtils.toMySqlString(x))); + } + + return true; + } + + private static boolean queryBlockFromIsNull(SQLSelectQuery query) { + if (query instanceof SQLSelectQueryBlock) { + return ((SQLSelectQueryBlock) query).getFrom() == null; + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOutFileExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOutFileExpr.java new file mode 100644 index 0000000000..183c1b0aed --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/expr/MySqlOutFileExpr.java @@ -0,0 +1,111 @@ +package com.alibaba.druid.sql.dialect.mysql.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; + +public class MySqlOutFileExpr extends MySqlObjectImpl implements SQLExpr { + + private static final long serialVersionUID = 1L; + private SQLExpr file; + private String charset; + + private SQLLiteralExpr columnsTerminatedBy; + private boolean columnsEnclosedOptionally = false; + private SQLLiteralExpr columnsEnclosedBy; + private SQLLiteralExpr columnsEscaped; + + private SQLLiteralExpr linesStartingBy; + private SQLLiteralExpr linesTerminatedBy; + + private SQLExpr ignoreLinesNumber; + + public MySqlOutFileExpr(){ + } + + public MySqlOutFileExpr(SQLExpr file){ + this.file = file; + } + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, file); + } + visitor.endVisit(this); + } + + public SQLExpr getFile() { + return file; + } + + public void setFile(SQLExpr file) { + this.file = file; + } + + public String getCharset() { + return charset; + } + + public void setCharset(String charset) { + this.charset = charset; + } + + public SQLLiteralExpr getColumnsTerminatedBy() { + return columnsTerminatedBy; + } + + public void setColumnsTerminatedBy(SQLLiteralExpr columnsTerminatedBy) { + this.columnsTerminatedBy = columnsTerminatedBy; + } + + public boolean isColumnsEnclosedOptionally() { + return columnsEnclosedOptionally; + } + + public void setColumnsEnclosedOptionally(boolean columnsEnclosedOptionally) { + this.columnsEnclosedOptionally = columnsEnclosedOptionally; + } + + public SQLLiteralExpr getColumnsEnclosedBy() { + return columnsEnclosedBy; + } + + public void setColumnsEnclosedBy(SQLLiteralExpr columnsEnclosedBy) { + this.columnsEnclosedBy = columnsEnclosedBy; + } + + public SQLLiteralExpr getColumnsEscaped() { + return columnsEscaped; + } + + public void setColumnsEscaped(SQLLiteralExpr columnsEscaped) { + this.columnsEscaped = columnsEscaped; + } + + public SQLLiteralExpr getLinesStartingBy() { + return linesStartingBy; + } + + public void setLinesStartingBy(SQLLiteralExpr linesStartingBy) { + this.linesStartingBy = linesStartingBy; + } + + public SQLLiteralExpr getLinesTerminatedBy() { + return linesTerminatedBy; + } + + public void setLinesTerminatedBy(SQLLiteralExpr linesTerminatedBy) { + this.linesTerminatedBy = linesTerminatedBy; + } + + public SQLExpr getIgnoreLinesNumber() { + return ignoreLinesNumber; + } + + public void setIgnoreLinesNumber(SQLExpr ignoreLinesNumber) { + this.ignoreLinesNumber = ignoreLinesNumber; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java index a22cb8f555..5e0811583b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java @@ -22,7 +22,6 @@ import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -30,55 +29,37 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; @SuppressWarnings("serial") public class MySqlSelectQueryBlock extends SQLSelectQueryBlock { - private boolean hignPriority; - private boolean straightJoin; + private boolean hignPriority; + private boolean straightJoin; - private boolean smallResult; - private boolean bigResult; - private boolean bufferResult; - private Boolean cache; - private boolean calcFoundRows; + private boolean smallResult; + private boolean bigResult; + private boolean bufferResult; + private Boolean cache; + private boolean calcFoundRows; - private SQLOrderBy orderBy; + private SQLOrderBy orderBy; - private Limit limit; + private Limit limit; - private SQLName procedureName; - private List procedureArgumentList = new ArrayList(); - private SQLExpr outFile; - private String outFileCharset; + private SQLName procedureName; + private List procedureArgumentList = new ArrayList(); - private SQLLiteralExpr outFileColumnsTerminatedBy; - private boolean outFileColumnsEnclosedOptionally = false; - private SQLLiteralExpr outFileColumnsEnclosedBy; - private SQLLiteralExpr outFileColumnsEscaped; + private SQLExpr into; - private SQLLiteralExpr outFileLinesStartingBy; - private SQLLiteralExpr outFileLinesTerminatedBy; - - private SQLExpr outFileIgnoreLinesNumber; - - private boolean forUpdate = false; - private boolean lockInShareMode = false; + private boolean forUpdate = false; + private boolean lockInShareMode = false; public MySqlSelectQueryBlock(){ } - public SQLExpr getOutFile() { - return outFile; + public SQLExpr getInto() { + return into; } - public void setOutFile(SQLExpr outFile) { - this.outFile = outFile; - } - - public String getOutFileCharset() { - return outFileCharset; - } - - public void setOutFileCharset(String charset) { - this.outFileCharset = charset; + public void setInto(SQLExpr into) { + this.into = into; } public boolean isForUpdate() { @@ -185,62 +166,6 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock { this.limit = limit; } - public SQLLiteralExpr getOutFileColumnsTerminatedBy() { - return outFileColumnsTerminatedBy; - } - - public void setOutFileColumnsTerminatedBy(SQLLiteralExpr outFileColumnsTerminatedBy) { - this.outFileColumnsTerminatedBy = outFileColumnsTerminatedBy; - } - - public boolean isOutFileColumnsEnclosedOptionally() { - return outFileColumnsEnclosedOptionally; - } - - public void setOutFileColumnsEnclosedOptionally(boolean outFileColumnsEnclosedOptionally) { - this.outFileColumnsEnclosedOptionally = outFileColumnsEnclosedOptionally; - } - - public SQLLiteralExpr getOutFileColumnsEnclosedBy() { - return outFileColumnsEnclosedBy; - } - - public void setOutFileColumnsEnclosedBy(SQLLiteralExpr outFileColumnsEnclosedBy) { - this.outFileColumnsEnclosedBy = outFileColumnsEnclosedBy; - } - - public SQLLiteralExpr getOutFileColumnsEscaped() { - return outFileColumnsEscaped; - } - - public void setOutFileColumnsEscaped(SQLLiteralExpr outFileColumnsEscaped) { - this.outFileColumnsEscaped = outFileColumnsEscaped; - } - - public SQLLiteralExpr getOutFileLinesStartingBy() { - return outFileLinesStartingBy; - } - - public void setOutFileLinesStartingBy(SQLLiteralExpr outFileLinesStartingBy) { - this.outFileLinesStartingBy = outFileLinesStartingBy; - } - - public SQLLiteralExpr getOutFileLinesTerminatedBy() { - return outFileLinesTerminatedBy; - } - - public void setOutFileLinesTerminatedBy(SQLLiteralExpr outFileLinesTerminatedBy) { - this.outFileLinesTerminatedBy = outFileLinesTerminatedBy; - } - - public SQLExpr getOutFileIgnoreLinesNumber() { - return outFileIgnoreLinesNumber; - } - - public void setOutFileIgnoreLinesNumber(SQLExpr outFileIgnoreLinesNumber) { - this.outFileIgnoreLinesNumber = outFileIgnoreLinesNumber; - } - @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { @@ -252,13 +177,7 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock { acceptChild(visitor, this.limit); acceptChild(visitor, this.procedureName); acceptChild(visitor, this.procedureArgumentList); - acceptChild(visitor, this.outFile); - acceptChild(visitor, this.outFileColumnsTerminatedBy); - acceptChild(visitor, this.outFileColumnsEnclosedBy); - acceptChild(visitor, this.outFileColumnsEscaped); - acceptChild(visitor, this.outFileLinesStartingBy); - acceptChild(visitor, this.outFileLinesTerminatedBy); - acceptChild(visitor, this.outFileIgnoreLinesNumber); + acceptChild(visitor, this.into); } visitor.endVisit(this); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index 6847923b07..d6900fe08a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -33,6 +33,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalUnit; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr.SearchModifier; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinition; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; @@ -110,6 +111,15 @@ public class MySqlExprParser extends SQLExprParser { public SQLExpr primary() throws ParserException { final Token tok = lexer.token(); + + if (identifierEquals("outfile")) { + lexer.nextToken(); + SQLExpr file = primary(); + SQLExpr expr = new MySqlOutFileExpr(file); + + return primaryRest(expr); + + } switch (tok) { case TRUE: diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index dc78fd3fef..507c03a5aa 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.parser.Lexer; @@ -111,8 +112,11 @@ public class MySqlSelectParser extends SQLSelectParser { if (lexer.token() == (Token.INTO)) { lexer.nextToken(); acceptIdentifier("OUTFILE"); - SQLExpr outFile = expr(); - queryBlock.setOutFile(outFile); + + MySqlOutFileExpr outFile = new MySqlOutFileExpr(); + outFile.setFile(expr()); + + queryBlock.setInto(outFile); if (identifierEquals("FIELDS") || identifierEquals("COLUMNS")) { lexer.nextToken(); @@ -121,23 +125,23 @@ public class MySqlSelectParser extends SQLSelectParser { lexer.nextToken(); accept(Token.BY); } - queryBlock.setOutFileColumnsTerminatedBy((SQLLiteralExpr) expr()); + outFile.setColumnsTerminatedBy((SQLLiteralExpr) expr()); if (identifierEquals("OPTIONALLY")) { lexer.nextToken(); - queryBlock.setOutFileColumnsEnclosedOptionally(true); + outFile.setColumnsEnclosedOptionally(true); } if (identifierEquals("ENCLOSED")) { lexer.nextToken(); accept(Token.BY); - queryBlock.setOutFileColumnsEnclosedBy((SQLLiteralExpr) expr()); + outFile.setColumnsEnclosedBy((SQLLiteralExpr) expr()); } if (identifierEquals("ESCAPED")) { lexer.nextToken(); accept(Token.BY); - queryBlock.setOutFileColumnsEscaped((SQLLiteralExpr) expr()); + outFile.setColumnsEscaped((SQLLiteralExpr) expr()); } } @@ -147,12 +151,12 @@ public class MySqlSelectParser extends SQLSelectParser { if (identifierEquals("STARTING")) { lexer.nextToken(); accept(Token.BY); - queryBlock.setOutFileLinesStartingBy((SQLLiteralExpr) expr()); + outFile.setLinesStartingBy((SQLLiteralExpr) expr()); } else { identifierEquals("TERMINATED"); lexer.nextToken(); accept(Token.BY); - queryBlock.setOutFileLinesTerminatedBy((SQLLiteralExpr) expr()); + outFile.setLinesTerminatedBy((SQLLiteralExpr) expr()); } } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index b3da9c8ec4..660cfedd93 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -19,6 +19,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; @@ -191,4 +192,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlSelectQueryBlock x); void endVisit(MySqlSelectQueryBlock x); + + boolean visit(MySqlOutFileExpr x); + + void endVisit(MySqlOutFileExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index c247564bf3..29e66ce230 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -7,6 +7,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; @@ -411,4 +412,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(MySqlOutFileExpr x) { + return true; + } + + @Override + public void endVisit(MySqlOutFileExpr x) { + + } + } 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 ec68acf43a..48e2e42a0a 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 @@ -36,11 +36,13 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropUser; @@ -57,7 +59,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinition; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; -import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement; @@ -135,49 +136,10 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV printSelectList(x.getSelectList()); - if (x.getOutFile() != null) { + if (x.getInto() != null) { println(); - print("INTO OUTFILE "); - x.getOutFile().accept(this); - if (x.getOutFileCharset() != null) { - print(" CHARACTER SET "); - print(x.getOutFileCharset()); - } - - if (x.getOutFileColumnsTerminatedBy() != null || x.getOutFileColumnsEnclosedBy() != null - || x.getOutFileColumnsEscaped() != null) { - print(" COLUMNS"); - if (x.getOutFileColumnsTerminatedBy() != null) { - print(" TERMINATED BY "); - x.getOutFileColumnsTerminatedBy().accept(this); - } - - if (x.getOutFileColumnsEnclosedBy() != null) { - if (x.isOutFileColumnsEnclosedOptionally()) { - print(" OPTIONALLY"); - } - print(" ENCLOSED BY "); - x.getOutFileColumnsEnclosedBy().accept(this); - } - - if (x.getOutFileColumnsEscaped() != null) { - print(" ESCAPED BY "); - x.getOutFileColumnsEscaped().accept(this); - } - } - - if (x.getOutFileLinesStartingBy() != null || x.getOutFileLinesTerminatedBy() != null) { - print(" LINES"); - if (x.getOutFileLinesStartingBy() != null) { - print(" STARTING BY "); - x.getOutFileLinesStartingBy().accept(this); - } - - if (x.getOutFileLinesTerminatedBy() != null) { - print(" TERMINATED BY "); - x.getOutFileLinesTerminatedBy().accept(this); - } - } + print("INTO "); + x.getInto().accept(this); } if (x.getFrom() != null) { @@ -1348,4 +1310,57 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public void endVisit(MySqlSelectQueryBlock x) { } + + @Override + public boolean visit(MySqlOutFileExpr x) { + print("OUTFILE "); + x.getFile().accept(this); + + if (x.getCharset() != null) { + print(" CHARACTER SET "); + print(x.getCharset()); + } + + if (x.getColumnsTerminatedBy() != null || x.getColumnsEnclosedBy() != null + || x.getColumnsEscaped() != null) { + print(" COLUMNS"); + if (x.getColumnsTerminatedBy() != null) { + print(" TERMINATED BY "); + x.getColumnsTerminatedBy().accept(this); + } + + if (x.getColumnsEnclosedBy() != null) { + if (x.isColumnsEnclosedOptionally()) { + print(" OPTIONALLY"); + } + print(" ENCLOSED BY "); + x.getColumnsEnclosedBy().accept(this); + } + + if (x.getColumnsEscaped() != null) { + print(" ESCAPED BY "); + x.getColumnsEscaped().accept(this); + } + } + + if (x.getLinesStartingBy() != null || x.getLinesTerminatedBy() != null) { + print(" LINES"); + if (x.getLinesStartingBy() != null) { + print(" STARTING BY "); + x.getLinesStartingBy().accept(this); + } + + if (x.getLinesTerminatedBy() != null) { + print(" TERMINATED BY "); + x.getLinesTerminatedBy().accept(this); + } + } + + return false; + } + + @Override + public void endVisit(MySqlOutFileExpr x) { + + } } 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 084fff2095..d557989f31 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 @@ -16,6 +16,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; @@ -474,4 +475,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlSelectQueryBlock x) { } + + @Override + public boolean visit(MySqlOutFileExpr x) { + return false; + } + + @Override + public void endVisit(MySqlOutFileExpr x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index a48be92831..e8938ce37b 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -287,10 +287,6 @@ public class SQLSelectParser extends SQLParser { return parseTableSourceRest(join); } - if (lexer.token() == Token.UNION) { - throw new SQLParseException("TODO"); - } - return tableSource; } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest.java index 14e476f05c..0470be8bd2 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest.java @@ -14,8 +14,19 @@ public class MySqlWallTest extends TestCase { Assert.assertFalse(WallUtils.isValidateMySql("select hex(load_file(0x633A2F77696E646F77732F7265706169722F73616D))")); Assert.assertTrue(WallUtils.isValidateMySql("select 'hex(load_file(0x633A2F77696E646F77732F7265706169722F73616D))'")); + + Assert.assertFalse(WallUtils.isValidateMySql("select 15,version()")); + Assert.assertTrue(WallUtils.isValidateMySql("select 15,'version'")); Assert.assertFalse(WallUtils.isValidateMySql("select 1 from information_schema.columns")); Assert.assertTrue(WallUtils.isValidateMySql("select 'information_schema.columns'")); + + Assert.assertFalse(WallUtils.isValidateMySql("select 1 from mysql.user")); + Assert.assertTrue(WallUtils.isValidateMySql("select 'mysql.user'")); + + Assert.assertFalse(WallUtils.isValidateMySql("select 0x3C3F706870206576616C28245F504F53545B2763275D293F3E into outfile '\\www\\edu\\1.php'")); + Assert.assertTrue(WallUtils.isValidateMySql("select 'outfile'")); + + Assert.assertFalse(WallUtils.isValidateMySql("select f1, f2 from t union select 1, 2")); } }