mysql parser support hints

This commit is contained in:
温少
2012-05-18 11:20:29 +08:00
13 changed files with 125 additions and 47 deletions
@@ -24,9 +24,11 @@ import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLPartitioningClause;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@SuppressWarnings("serial")
public class MySqlCreateTableStatement extends SQLCreateTableStatement {
public class MySqlCreateTableStatement extends SQLCreateTableStatement implements MySqlStatement {
private boolean ifNotExiists = false;
@@ -111,4 +113,21 @@ public class MySqlCreateTableStatement extends SQLCreateTableStatement {
this.ifNotExiists = ifNotExiists;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof MySqlASTVisitor) {
accept0((MySqlASTVisitor) visitor);
} else {
throw new IllegalArgumentException("not support visitor type : " + visitor.getClass().getName());
}
}
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
this.acceptChild(visitor, getHints());
this.acceptChild(visitor, getTableSource());
this.acceptChild(visitor, getTableElementList());
}
visitor.endVisit(this);
}
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.mysql.ast.statement;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObjectImpl;
@@ -30,29 +31,39 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@SuppressWarnings("serial")
public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlObject {
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<SQLExpr> procedureArgumentList = new ArrayList<SQLExpr>();
private SQLName procedureName;
private List<SQLExpr> procedureArgumentList = new ArrayList<SQLExpr>();
private boolean forUpdate = false;
private boolean lockInShareMode = false;
private boolean forUpdate = false;
private boolean lockInShareMode = false;
private List<SQLCommentHint> hints = new ArrayList<SQLCommentHint>();
public MySqlSelectQueryBlock(){
}
public List<SQLCommentHint> getHints() {
return hints;
}
public void setHints(List<SQLCommentHint> hints) {
this.hints = hints;
}
public boolean isForUpdate() {
return forUpdate;
}
@@ -163,7 +174,7 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO
accept0((MySqlASTVisitor) visitor);
return;
}
if (visitor.visit(this)) {
acceptChild(visitor, this.selectList);
acceptChild(visitor, this.from);
@@ -178,7 +189,7 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO
visitor.endVisit(this);
}
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
@@ -389,7 +389,7 @@ public class MySqlLexer extends Lexer {
}
if (isHint) {
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 2).trim();
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 1);
token = Token.HINT;
} else {
stringVal = new String(buf, np, sp);
@@ -64,6 +64,10 @@ public class MySqlSelectParser extends SQLSelectParser {
if (lexer.token() == Token.SELECT) {
lexer.nextToken();
if (lexer.token() == Token.HINT) {
this.createExprParser().parseHints(queryBlock.getHints());
}
if (lexer.token() == (Token.DISTINCT)) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
@@ -37,6 +37,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen
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.MySqlCreateIndexStatement;
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.MySqlDeleteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement;
@@ -495,4 +496,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
boolean visit(MySqlAlterTableOption x);
void endVisit(MySqlAlterTableOption x);
boolean visit(MySqlCreateTableStatement x);
void endVisit(MySqlCreateTableStatement x);
}
@@ -22,6 +22,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen
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.MySqlCreateIndexStatement;
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;
@@ -1079,4 +1080,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements
public void endVisit(MySqlAlterTableOption x) {
}
@Override
public boolean visit(MySqlCreateTableStatement x) {
return true;
}
@Override
public void endVisit(MySqlCreateTableStatement x) {
}
}
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.mysql.visitor;
import java.util.Map;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
@@ -161,6 +162,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
print("SELECT ");
for (SQLCommentHint hint : x.getHints()) {
hint.accept(this);
print(' ');
}
if (SQLSetQuantifier.ALL == x.getDistionOption()) print("ALL ");
else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) print("DISTINCT ");
@@ -359,20 +366,22 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
return false;
}
public boolean visit(SQLCreateTableStatement x) {
public boolean visit(MySqlCreateTableStatement x) {
MySqlCreateTableStatement mysqlCreateTableStatement = null;
if (x instanceof MySqlCreateTableStatement) {
mysqlCreateTableStatement = (MySqlCreateTableStatement) x;
print("CREATE ");
for (SQLCommentHint hint : x.getHints()) {
hint.accept(this);
print(' ');
}
if (SQLCreateTableStatement.Type.GLOBAL_TEMPORARY.equals(x.getType())) {
print("CREATE TEMPORARY TABLE ");
print("TEMPORARY TABLE ");
} else {
print("CREATE TABLE ");
print("TABLE ");
}
if (mysqlCreateTableStatement != null && mysqlCreateTableStatement.isIfNotExiists()) {
if (x.isIfNotExiists()) {
print("IF NOT EXISTS ");
}
@@ -391,20 +400,18 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
println();
print(")");
if (mysqlCreateTableStatement != null) {
for (Map.Entry<String, String> option : mysqlCreateTableStatement.getTableOptions().entrySet()) {
print(" ");
print(option.getKey());
print(" = ");
print(option.getValue());
}
for (Map.Entry<String, String> option : x.getTableOptions().entrySet()) {
print(" ");
print(option.getKey());
print(" = ");
print(option.getValue());
}
if (mysqlCreateTableStatement != null && mysqlCreateTableStatement.getQuery() != null) {
if (x.getQuery() != null) {
print(" ");
incrementIndent();
println();
mysqlCreateTableStatement.getQuery().accept(this);
x.getQuery().accept(this);
decrementIndent();
}
@@ -2525,12 +2532,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
public boolean visit(MySqlAlterTableCharacter x) {
print("CHARACTER SET = ");
x.getCharacterSet().accept(this);
if (x.getCollate() != null) {
print(", COLLATE = ");
x.getCollate().accept(this);
}
return false;
}
@@ -2563,7 +2570,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public void endVisit(MySqlAlterTableAddIndex x) {
}
@Override
@@ -2576,6 +2583,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public void endVisit(MySqlAlterTableOption x) {
}
@Override
public void endVisit(MySqlCreateTableStatement x) {
}
}
@@ -4,6 +4,7 @@ import java.util.Map;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
@@ -32,6 +33,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatemen
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.MySqlCreateIndexStatement;
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;
@@ -1143,4 +1145,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
public void endVisit(MySqlAlterTableOption x) {
}
@Override
public boolean visit(MySqlCreateTableStatement x) {
return super.visit((SQLCreateTableStatement) x);
}
@Override
public void endVisit(MySqlCreateTableStatement x) {
}
}
@@ -239,7 +239,7 @@ public class OracleLexer extends Lexer {
}
if (isHint) {
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 2).trim();
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 1);
token = Token.HINT;
} else {
stringVal = new String(buf, np, sp);
@@ -15,7 +15,6 @@
*/
package com.alibaba.druid.sql.dialect.oracle.visitor;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.expr.SQLObjectCreateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
@@ -17,7 +17,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLHint;
@@ -906,11 +905,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
@Override
public void endVisit(SQLCommentHint x) {
}
@Override
public void endVisit(OracleIntervalExpr x) {
@@ -2181,7 +2175,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
print(x.getType());
print(" ");
}
print("INDEX ");
x.getName().accept(this);
@@ -1092,7 +1092,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter {
}
public boolean visit(SQLCommentHint x) {
print("/*");
print(x.getText());
print("*/");
return false;
}
}
@@ -17,6 +17,15 @@ public class HintsTest extends TestCase {
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("CREATE TABLE t (\n\ta INT\n)", output);
Assert.assertEquals("CREATE /*!32302 TEMPORARY */ TABLE t (\n\ta INT\n)", output);
}
public void test_hints_1() throws Exception {
String sql = "SELECT /*! STRAIGHT_JOIN */ col1 FROM table1,table2";
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatementList().get(0);
parser.match(Token.EOF);
String output = SQLUtils.toMySqlString(stmt);
Assert.assertEquals("SELECT /*! STRAIGHT_JOIN */ col1\nFROM table1, table2", output);
}
}