mysql parser bug fixed

This commit is contained in:
温少
2012-05-17 08:14:20 +08:00
parent de1d141e4b
commit fbad5c8804
5 changed files with 222 additions and 28 deletions
@@ -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);
@@ -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;
@@ -1356,6 +1355,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 +1388,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 +1407,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 +1647,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 +1679,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 +1689,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) {
@@ -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;
}
@@ -39,4 +39,67 @@ public class DMLInsertParserTest extends TestCase {
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT INTO t1\nVALUES (123, ?) ON DUPLICATE KEY UPDATE ex.col1 = ?", output);
}
public void testInsert_3() throws Exception {
String sql = "insErt LOW_PRIORITY t1 valueS (12e-2,1,2), (?),(default)";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1\nVALUES (0.12, 1, 2), (?), (DEFAULT)", output);
}
public void testInsert_4() throws Exception {
String sql = "insErt LOW_PRIORITY t1 select id from t1";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1\nSELECT id\nFROM t1", output);
}
public void testInsert_5() throws Exception {
String sql = "insErt LOW_PRIORITY t1 (select id from t1) oN dupLicatE key UPDATE ex.col1=?, col2=12";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1\nSELECT id\nFROM t1 ON DUPLICATE KEY UPDATE ex.col1 = ?, col2 = 12", output);
}
public void testInsert_6() throws Exception {
String sql = "insErt LOW_PRIORITY t1 (t1.col1) valueS (123),('12''34')";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1 (t1.col1)\nVALUES (123), ('12''34')", output);
}
public void testInsert_7() throws Exception {
String sql = "insErt LOW_PRIORITY t1 (col1, t1.col2) VALUE (123,'123\\'4') oN dupLicatE key UPDATE ex.col1=?";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1 (col1, t1.col2)\nVALUES (123, '123''4') ON DUPLICATE KEY UPDATE ex.col1 = ?", output);
}
public void testInsert_8() throws Exception {
String sql = "insErt LOW_PRIORITY t1 (col1, t1.col2) select id from t3 oN dupLicatE key UPDATE ex.col1=?";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY INTO t1 (col1, t1.col2)\nSELECT id\nFROM t3 ON DUPLICATE KEY UPDATE ex.col1 = ?", output);
}
public void testInsert_9() throws Exception {
String sql = "insErt LOW_PRIORITY IGNORE intO t1 (col1) ( select id from t3) ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("INSERT LOW_PRIORITY IGNORE INTO t1 (col1)\nSELECT id\nFROM t3", output);
}
}
@@ -0,0 +1,112 @@
package com.alibaba.druid.bvt.sql.cobar;
import org.junit.Assert;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.parser.Token;
import junit.framework.TestCase;
public class DMLReplaceParserTest extends TestCase {
public void testReplace_0() throws Exception {
String sql = "ReplaCe LOW_PRIORITY intO test.t1 seT t1.id1:=?, id2='123'";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO test.t1 (t1.id1, id2)\nVALUES (?, '123')", output);
}
public void testReplace_1() throws Exception {
String sql = "ReplaCe test.t1 seT t1.id1:=? ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE INTO test.t1 (t1.id1)\nVALUES (?)", output);
}
public void testReplace_2() throws Exception {
String sql = "ReplaCe t1 value (123,?) ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE INTO t1\nVALUES (123, ?)", output);
}
public void testReplace_3() throws Exception {
String sql = "ReplaCe LOW_PRIORITY t1 valueS (12e-2), (?)";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1\nVALUES (0.12), (?)", output);
}
public void testReplace_4() throws Exception {
String sql = "ReplaCe LOW_PRIORITY t1 select id from t1";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1\n\tSELECT id\n\tFROM t1", output);
}
public void testReplace_5() throws Exception {
String sql = "ReplaCe delayed t1 select id from t1";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE DELAYED INTO t1\n\tSELECT id\n\tFROM t1", output);
}
public void testReplace_6() throws Exception {
String sql = "ReplaCe LOW_PRIORITY t1 (select id from t1) ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1\n\tSELECT id\n\tFROM t1", output);
}
public void testReplace_7() throws Exception {
String sql = "ReplaCe LOW_PRIORITY t1 (t1.col1) valueS (123),('12''34')";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (t1.col1)\nVALUES (123), ('12''34')", output);
}
public void testReplace_8() throws Exception {
String sql = "ReplaCe LOW_PRIORITY t1 (col1, t1.col2) VALUE (123,'123\\'4') ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (col1, t1.col2)\nVALUES (123, '123''4')", output);
}
public void testReplace_9() throws Exception {
String sql = "REPLACE LOW_PRIORITY t1 (col1, t1.col2) select id from t3 ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (col1, t1.col2)\n\tSELECT id\n\tFROM t3", output);
}
public void testReplace_10() throws Exception {
String sql = "replace LOW_PRIORITY intO t1 (col1) ( select id from t3) ";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (col1)\n\tSELECT id\n\tFROM t3", output);
}
}