mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
mysql parser bug fixed
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.alibaba.druid.sql.ast.statement;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLUnionQuery extends SQLSelectQuery {
|
||||
@@ -24,6 +25,7 @@ public class SQLUnionQuery extends SQLSelectQuery {
|
||||
private SQLSelectQuery left;
|
||||
private SQLSelectQuery right;
|
||||
private SQLUnionOperator operator = SQLUnionOperator.UNION;
|
||||
private SQLOrderBy orderBy;
|
||||
|
||||
public SQLUnionOperator getOperator() {
|
||||
return operator;
|
||||
@@ -53,6 +55,14 @@ public class SQLUnionQuery extends SQLSelectQuery {
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public SQLOrderBy getOrderBy() {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
public void setOrderBy(SQLOrderBy orderBy) {
|
||||
this.orderBy = orderBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
|
||||
-7
@@ -22,7 +22,6 @@ import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
|
||||
public class MySqlReplicateStatement extends MySqlStatementImpl {
|
||||
@@ -35,7 +34,6 @@ public class MySqlReplicateStatement extends MySqlStatementImpl {
|
||||
private SQLName tableName;
|
||||
private final List<SQLExpr> columns = new ArrayList<SQLExpr>();
|
||||
private List<ValuesClause> valuesList = new ArrayList<ValuesClause>();
|
||||
private List<SQLUpdateSetItem> setItems = new ArrayList<SQLUpdateSetItem>();
|
||||
private SQLQueryExpr query;
|
||||
|
||||
public SQLName getTableName() {
|
||||
@@ -79,16 +77,11 @@ public class MySqlReplicateStatement extends MySqlStatementImpl {
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
public List<SQLUpdateSetItem> getSetItems() {
|
||||
return setItems;
|
||||
}
|
||||
|
||||
public void accept0(MySqlASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, tableName);
|
||||
acceptChild(visitor, columns);
|
||||
acceptChild(visitor, valuesList);
|
||||
acceptChild(visitor, setItems);
|
||||
acceptChild(visitor, query);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
|
||||
@@ -38,6 +38,8 @@ import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr.Search
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlUserName;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinition;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.ParserException;
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
@@ -580,4 +582,28 @@ public class MySqlExprParser extends SQLExprParser {
|
||||
}
|
||||
return super.nameRest(name);
|
||||
}
|
||||
|
||||
public Limit parseLimit() {
|
||||
if (lexer.token() == Token.LIMIT) {
|
||||
lexer.nextToken();
|
||||
|
||||
MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
|
||||
|
||||
SQLExpr temp = this.expr();
|
||||
if (lexer.token() == (Token.COMMA)) {
|
||||
limit.setOffset(temp);
|
||||
lexer.nextToken();
|
||||
limit.setRowCount(this.expr());
|
||||
} else if (identifierEquals("OFFSET")) {
|
||||
limit.setRowCount(temp);
|
||||
lexer.nextToken();
|
||||
limit.setOffset(this.expr());
|
||||
} else {
|
||||
limit.setRowCount(temp);
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,12 @@ 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.ast.statement.SQLTableSource;
|
||||
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.MySqlSelectGroupBy;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.ParserException;
|
||||
import com.alibaba.druid.sql.parser.SQLSelectParser;
|
||||
@@ -177,24 +180,7 @@ public class MySqlSelectParser extends SQLSelectParser {
|
||||
queryBlock.setOrderBy(this.createExprParser().parseOrderBy());
|
||||
|
||||
if (lexer.token() == Token.LIMIT) {
|
||||
lexer.nextToken();
|
||||
|
||||
MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
|
||||
|
||||
SQLExpr temp = this.createExprParser().expr();
|
||||
if (lexer.token() == (Token.COMMA)) {
|
||||
limit.setOffset(temp);
|
||||
lexer.nextToken();
|
||||
limit.setRowCount(createExprParser().expr());
|
||||
} else if (identifierEquals("OFFSET")) {
|
||||
limit.setRowCount(temp);
|
||||
lexer.nextToken();
|
||||
limit.setOffset(createExprParser().expr());
|
||||
} else {
|
||||
limit.setRowCount(temp);
|
||||
}
|
||||
|
||||
queryBlock.setLimit(limit);
|
||||
queryBlock.setLimit(parseLimit());
|
||||
}
|
||||
|
||||
if (identifierEquals("PROCEDURE")) {
|
||||
@@ -271,5 +257,20 @@ public class MySqlSelectParser extends SQLSelectParser {
|
||||
|
||||
return super.parseTableSourceRest(tableSource);
|
||||
}
|
||||
|
||||
|
||||
protected MySqlUnionQuery createSQLUnionQuery() {
|
||||
return new MySqlUnionQuery();
|
||||
}
|
||||
|
||||
public SQLUnionQuery unionRest(SQLUnionQuery union) {
|
||||
if (lexer.token() == Token.LIMIT) {
|
||||
MySqlUnionQuery mysqlUnionQuery = (MySqlUnionQuery) union;
|
||||
mysqlUnionQuery.setLimit(parseLimit());
|
||||
}
|
||||
return super.unionRest(union);
|
||||
}
|
||||
|
||||
public Limit parseLimit() {
|
||||
return this.createExprParser().parseLimit();
|
||||
}
|
||||
}
|
||||
|
||||
+48
-37
@@ -22,7 +22,6 @@ import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
@@ -32,11 +31,11 @@ import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableAddColumn;
|
||||
@@ -60,7 +59,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStateme
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplicateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlResetStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
|
||||
@@ -1356,6 +1354,17 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
SQLName tableName = exprParser.name();
|
||||
stmt.setTableName(tableName);
|
||||
|
||||
if (lexer.token() == Token.LPAREN) {
|
||||
lexer.nextToken();
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
|
||||
stmt.setQuery(queryExpr);
|
||||
} else {
|
||||
this.exprParser.exprList(stmt.getColumns());
|
||||
}
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.VALUES || identifierEquals("VALUE")) {
|
||||
lexer.nextToken();
|
||||
|
||||
@@ -1378,13 +1387,17 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
stmt.setQuery(queryExpr);
|
||||
} else if (lexer.token() == Token.SET) {
|
||||
lexer.nextToken();
|
||||
for (;;) {
|
||||
SQLUpdateSetItem item = new SQLUpdateSetItem();
|
||||
item.setColumn(this.exprParser.name());
|
||||
accept(Token.EQ);
|
||||
item.setValue(this.exprParser.expr());
|
||||
|
||||
stmt.getSetItems().add(item);
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
|
||||
stmt.getValuesList().add(values);
|
||||
for (;;) {
|
||||
stmt.getColumns().add(this.exprParser.name());
|
||||
if (lexer.token() == Token.COLONEQ) {
|
||||
lexer.nextToken();
|
||||
} else {
|
||||
accept(Token.EQ);
|
||||
}
|
||||
values.getValues().add(this.exprParser.expr());
|
||||
|
||||
if (lexer.token() == (Token.COMMA)) {
|
||||
lexer.nextToken();
|
||||
@@ -1393,6 +1406,11 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
break;
|
||||
}
|
||||
} else if (lexer.token() == Token.LPAREN) {
|
||||
lexer.nextToken();
|
||||
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
|
||||
stmt.setQuery(queryExpr);
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
return stmt;
|
||||
@@ -1628,7 +1646,13 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
if (lexer.token() == (Token.LPAREN)) {
|
||||
lexer.nextToken();
|
||||
this.exprParser.exprList(insertStatement.getColumns());
|
||||
if (lexer.token() == (Token.SELECT)) {
|
||||
SQLSelect select = this.exprParser.createSelectParser().select();
|
||||
select.setParent(insertStatement);
|
||||
insertStatement.setQuery(select);
|
||||
} else {
|
||||
this.exprParser.exprList(insertStatement.getColumns());
|
||||
}
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
@@ -1654,7 +1678,7 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
|
||||
insertStatement.getValuesList().add(values);
|
||||
|
||||
|
||||
for (;;) {
|
||||
SQLName name = this.exprParser.name();
|
||||
insertStatement.getColumns().add(name);
|
||||
@@ -1664,18 +1688,25 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
accept(Token.COLONEQ);
|
||||
}
|
||||
values.getValues().add(this.exprParser.expr());
|
||||
|
||||
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextToken();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (lexer.token() == (Token.SELECT)) {
|
||||
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
|
||||
insertStatement.setQuery(queryExpr.getSubQuery());
|
||||
SQLSelect select = this.exprParser.createSelectParser().select();
|
||||
select.setParent(insertStatement);
|
||||
insertStatement.setQuery(select);
|
||||
} else if (lexer.token() == (Token.LPAREN)) {
|
||||
lexer.nextToken();
|
||||
SQLSelect select = this.exprParser.createSelectParser().select();
|
||||
select.setParent(insertStatement);
|
||||
insertStatement.setQuery(select);
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.ON) {
|
||||
@@ -1898,28 +1929,8 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
}
|
||||
}
|
||||
|
||||
private Limit parseLimit() {
|
||||
if (lexer.token() == Token.LIMIT) {
|
||||
lexer.nextToken();
|
||||
|
||||
MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
|
||||
|
||||
SQLExpr temp = this.exprParser.expr();
|
||||
if (lexer.token() == (Token.COMMA)) {
|
||||
limit.setOffset(temp);
|
||||
lexer.nextToken();
|
||||
limit.setRowCount(exprParser.expr());
|
||||
} else if (identifierEquals("OFFSET")) {
|
||||
limit.setRowCount(temp);
|
||||
lexer.nextToken();
|
||||
limit.setOffset(exprParser.expr());
|
||||
} else {
|
||||
limit.setRowCount(temp);
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
return null;
|
||||
public Limit parseLimit() {
|
||||
return ((MySqlExprParser) this.exprParser).parseLimit();
|
||||
}
|
||||
|
||||
public SQLStatement parseAlter() {
|
||||
|
||||
@@ -795,7 +795,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
}
|
||||
|
||||
if (x.getQuery() != null) {
|
||||
print(" ");
|
||||
println();
|
||||
x.getQuery().accept(this);
|
||||
}
|
||||
|
||||
@@ -937,12 +937,6 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
|
||||
x.getQuery().accept(this);
|
||||
}
|
||||
|
||||
if (x.getSetItems().size() != 0) {
|
||||
println();
|
||||
print("SET ");
|
||||
printAndAccept(x.getSetItems(), ", ");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,12 +52,25 @@ public class SQLSelectParser extends SQLParser {
|
||||
|
||||
return select;
|
||||
}
|
||||
|
||||
protected SQLUnionQuery createSQLUnionQuery() {
|
||||
return new SQLUnionQuery();
|
||||
}
|
||||
|
||||
public SQLUnionQuery unionRest(SQLUnionQuery union) {
|
||||
if (lexer.token() == Token.ORDER) {
|
||||
SQLOrderBy orderBy = this.createExprParser().parseOrderBy();
|
||||
union.setOrderBy(orderBy);
|
||||
return unionRest(union);
|
||||
}
|
||||
return union;
|
||||
}
|
||||
|
||||
public SQLSelectQuery queryRest(SQLSelectQuery selectQuery) throws ParserException {
|
||||
if (lexer.token() == Token.UNION) {
|
||||
lexer.nextToken();
|
||||
|
||||
SQLUnionQuery union = new SQLUnionQuery();
|
||||
SQLUnionQuery union = createSQLUnionQuery();
|
||||
union.setLeft(selectQuery);
|
||||
|
||||
if (lexer.token() == Token.ALL) {
|
||||
@@ -68,7 +81,7 @@ public class SQLSelectParser extends SQLParser {
|
||||
SQLSelectQuery right = this.query();
|
||||
union.setRight(right);
|
||||
|
||||
return union;
|
||||
return unionRest(union);
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.INTERSECT) {
|
||||
|
||||
@@ -168,6 +168,18 @@ public class SQLStatementParser extends SQLParser {
|
||||
if (parseStatementListDialect(statementList)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.LPAREN) {
|
||||
char mark_ch = lexer.current();
|
||||
int mark_bp = lexer.bp();
|
||||
lexer.nextToken();
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
lexer.reset(mark_bp, mark_ch, Token.LPAREN);
|
||||
SQLStatement stmt = parseSelect();
|
||||
statementList.add(stmt);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user