mysql parser bug fixed

This commit is contained in:
温少
2012-05-17 08:39:07 +08:00
parent de1d141e4b
commit 8e9e94e754
10 changed files with 307 additions and 72 deletions
@@ -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)) {
@@ -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();
}
}
@@ -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());
}