refactor && enhance mysql sql parser support

This commit is contained in:
温少
2012-05-15 16:30:39 +08:00
parent 31e71f6c91
commit fc222e6172
32 changed files with 1660 additions and 88 deletions
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.ast.expr;
import java.util.BitSet;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
/**
@@ -28,7 +29,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
*
* @author WENSHAO
*/
public class SQLBitStringLiteralExpr extends SQLLiteralExpr {
public class SQLBitStringLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,9 +15,10 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLDateLiteralExpr extends SQLLiteralExpr {
public class SQLDateLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -1,8 +1,9 @@
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLDefaultExpr extends SQLLiteralExpr {
public class SQLDefaultExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,9 +15,12 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.util.HexBin;
import com.alibaba.druid.util.IOUtils;
public class SQLHexExpr extends SQLLiteralExpr {
public class SQLHexExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -76,4 +79,8 @@ public class SQLHexExpr extends SQLLiteralExpr {
}
return true;
}
public byte[] toBytes() {
return HexBin.decode(this.hex);
}
}
@@ -15,9 +15,10 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLHexStringLiteralExpr extends SQLLiteralExpr {
public class SQLHexStringLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
/**
@@ -22,7 +23,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor;
*
* @author WENSHAO
*/
public class SQLIntervalLiteralExpr extends SQLLiteralExpr {
public class SQLIntervalLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,14 +15,9 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
public abstract class SQLLiteralExpr extends SQLExprImpl {
public interface SQLLiteralExpr extends SQLExpr {
private static final long serialVersionUID = 1L;
public SQLLiteralExpr(){
}
}
@@ -15,9 +15,10 @@
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLNullExpr extends SQLLiteralExpr {
public class SQLNullExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,7 +15,9 @@
*/
package com.alibaba.druid.sql.ast.expr;
public abstract class SQLNumericLiteralExpr extends SQLLiteralExpr {
import com.alibaba.druid.sql.ast.SQLExprImpl;
public abstract class SQLNumericLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -15,7 +15,9 @@
*/
package com.alibaba.druid.sql.ast.expr;
public abstract class SQLTextLiteralExpr extends SQLLiteralExpr {
import com.alibaba.druid.sql.ast.SQLExprImpl;
public abstract class SQLTextLiteralExpr extends SQLExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -24,10 +24,16 @@ public class SQLVariantRefExpr extends SQLExprImpl {
private String name;
public SQLVariantRefExpr(String name){
private boolean global = false;
public SQLVariantRefExpr(String name){
this.name = name;
}
public SQLVariantRefExpr(String name, boolean global){
this.name = name;
this.global = global;
}
public SQLVariantRefExpr(){
@@ -82,4 +88,12 @@ public class SQLVariantRefExpr extends SQLExprImpl {
return true;
}
public boolean isGlobal() {
return global;
}
public void setGlobal(boolean global) {
this.global = global;
}
}
@@ -19,7 +19,7 @@ import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class MySqlBinaryExpr extends SQLLiteralExpr implements MySqlExpr {
public class MySqlBinaryExpr extends MySqlExprImpl implements MySqlExpr, SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -47,7 +47,7 @@ public class MySqlBinaryExpr extends SQLLiteralExpr implements MySqlExpr {
this.accept0((MySqlASTVisitor) visitor);
}
protected void accept0(MySqlASTVisitor visitor) {
public void accept0(MySqlASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
@@ -19,7 +19,7 @@ import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class MySqlBooleanExpr extends SQLLiteralExpr implements MySqlExpr {
public class MySqlBooleanExpr extends MySqlExprImpl implements MySqlExpr, SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@@ -46,7 +46,7 @@ public class MySqlBooleanExpr extends SQLLiteralExpr implements MySqlExpr {
this.accept0((MySqlASTVisitor) visitor);
}
protected void accept0(MySqlASTVisitor visitor) {
public void accept0(MySqlASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
@@ -0,0 +1,10 @@
package com.alibaba.druid.sql.dialect.mysql.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
public abstract class MySqlExprImpl extends MySqlObjectImpl implements SQLExpr {
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,16 @@
package com.alibaba.druid.sql.dialect.mysql.ast.expr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlHexadecimalExpr extends MySqlExprImpl implements SQLLiteralExpr {
private static final long serialVersionUID = 1L;
@Override
public void accept0(MySqlASTVisitor visitor) {
}
}
@@ -0,0 +1,34 @@
package com.alibaba.druid.sql.dialect.mysql.ast.statement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
public class MySqlSetTransactionIsolationLevelStatement extends MySqlStatementImpl {
private static final long serialVersionUID = 1L;
private Boolean global;
private String level;
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public void accept0(MySqlASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
}
public Boolean getGlobal() {
return global;
}
public void setGlobal(Boolean global) {
this.global = global;
}
}
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr;
@@ -132,6 +133,21 @@ public class MySqlExprParser extends SQLExprParser {
String aliasValue = lexer.stringVal();
lexer.nextToken();
return primaryRest(new SQLCharExpr(aliasValue));
case VARIANT:
SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(lexer.stringVal());
lexer.nextToken();
if (varRefExpr.getName().equalsIgnoreCase("@@global")) {
accept(Token.DOT);
varRefExpr = new SQLVariantRefExpr(lexer.stringVal(), true);
lexer.nextToken();
} else if (varRefExpr.getName().equals("@") && lexer.token() == Token.LITERAL_CHARS) {
varRefExpr.setName("@'" + lexer.stringVal() + "'");
lexer.nextToken();
} else if (varRefExpr.getName().equals("@@") && lexer.token() == Token.LITERAL_CHARS) {
varRefExpr.setName("@@'" + lexer.stringVal() + "'");
lexer.nextToken();
}
return primaryRest(varRefExpr);
default:
return super.primary();
}
@@ -496,4 +512,35 @@ public class MySqlExprParser extends SQLExprParser {
return expr;
}
public SQLAssignItem parseAssignItem() {
SQLAssignItem item = new SQLAssignItem();
SQLExpr var = primary();
if (var instanceof SQLIdentifierExpr) {
String ident = ((SQLIdentifierExpr) var).getName();
if ("GLOBAL".equalsIgnoreCase(ident)) {
ident = lexer.stringVal();
lexer.nextToken();
var = new SQLVariantRefExpr(ident, true);
} else if ("SESSION".equalsIgnoreCase(ident)) {
ident = lexer.stringVal();
lexer.nextToken();
var = new SQLVariantRefExpr(ident, false);
} else {
var = new SQLVariantRefExpr(ident);
}
}
item.setTarget(var);
if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
} else {
accept(Token.EQ);
}
item.setValue(expr());
return item;
}
}
@@ -95,7 +95,6 @@ public class MySqlLexer extends Lexer {
map.put("CAST", Token.CAST);
map.put("IN", Token.IN);
map.put("ASC", Token.ASC);
map.put("DESC", Token.DESC);
map.put("LIKE", Token.LIKE);
map.put("ESCAPE", Token.ESCAPE);
map.put("BETWEEN", Token.BETWEEN);
@@ -128,6 +127,71 @@ public class MySqlLexer extends Lexer {
super.keywods = DEFAULT_MYSQL_KEYWORDS;
}
public void scanVariable() {
final char first = ch;
if (ch != '@' && ch != ':' && ch != '#') {
throw new SQLParseException("illegal variable");
}
int hash = first;
np = bp;
sp = 1;
if (buf[bp + 1] == '@') {
ch = buf[++bp];
hash = 31 * hash + ch;
sp++;
}
if (buf[bp + 1] == '`') {
++bp;
++sp;
char ch;
for (;;) {
ch = buf[++bp];
if (ch == '`') {
sp++;
ch = buf[++bp];
break;
} else if (ch == EOI) {
throw new SQLParseException("illegal identifier");
}
hash = 31 * hash + ch;
sp++;
continue;
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
token = Token.VARIANT;
} else {
for (;;) {
ch = buf[++bp];
if (!isIdentifierChar(ch)) {
break;
}
hash = 31 * hash + ch;
sp++;
continue;
}
}
this.ch = buf[bp];
stringVal = symbolTable.addSymbol(buf, np, sp, hash);
token = Token.VARIANT;
}
public void scanIdentifier() {
final char first = ch;
@@ -25,10 +25,12 @@ 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;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
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;
@@ -50,6 +52,7 @@ 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.MySqlSetTransactionIsolationLevelStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatement;
@@ -84,11 +87,11 @@ public class MySqlStatementParser extends SQLStatementParser {
public SQLSelectStatement parseSelect() throws ParserException {
return new SQLSelectStatement(new MySqlSelectParser(lexer).select());
}
public SQLUpdateStatement parseUpdateStatement() throws ParserException {
MySqlUpdateStatement stmt = (MySqlUpdateStatement) super.parseUpdateStatement();
if (lexer.token() == Token.LIMIT) {
MySqlUpdateStatement stmt = (MySqlUpdateStatement) super.parseUpdateStatement();
if (lexer.token() == Token.LIMIT) {
lexer.nextToken();
MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit();
@@ -105,16 +108,16 @@ public class MySqlStatementParser extends SQLStatementParser {
} else {
limit.setRowCount(temp);
}
stmt.setLimit(limit);
}
return stmt;
}
return stmt;
}
protected MySqlUpdateStatement createUpdateStatement() {
return new MySqlUpdateStatement();
}
protected MySqlUpdateStatement createUpdateStatement() {
return new MySqlUpdateStatement();
}
public MySqlDeleteStatement parseDeleteStatement() throws ParserException {
MySqlDeleteStatement deleteStatement = new MySqlDeleteStatement();
@@ -375,7 +378,7 @@ public class MySqlStatementParser extends SQLStatementParser {
return true;
}
if (identifierEquals("DESCRIBE")) {
if (identifierEquals("DESC") || identifierEquals("DESCRIBE")) {
SQLStatement stmt = parseDescribe();
statementList.add(stmt);
return true;
@@ -384,8 +387,12 @@ public class MySqlStatementParser extends SQLStatementParser {
return false;
}
public SQLStatement parseDescribe() throws ParserException {
acceptIdentifier("DESCRIBE");
public MySqlDescribeStatement parseDescribe() throws ParserException {
if (identifierEquals("DESC") || identifierEquals("DESCRIBE")) {
lexer.nextToken();
} else {
throw new ParserException("expect DESC, actual " + lexer.token());
}
MySqlDescribeStatement stmt = new MySqlDescribeStatement();
stmt.setObject(this.exprParser.name());
@@ -1067,4 +1074,72 @@ public class MySqlStatementParser extends SQLStatementParser {
public SQLSelectParser createSQLSelectParser() {
return new MySqlSelectParser(this.lexer);
}
public SQLStatement parseSet() throws ParserException {
accept(Token.SET);
Boolean global = null;
if (identifierEquals("GLOBAL")) {
global = Boolean.TRUE;
lexer.nextToken();
} else if (identifierEquals("SESSION")) {
global = Boolean.FALSE;
lexer.nextToken();
}
if (identifierEquals("TRANSACTION")) {
lexer.nextToken();
acceptIdentifier("ISOLATION");
acceptIdentifier("LEVEL");
MySqlSetTransactionIsolationLevelStatement stmt = new MySqlSetTransactionIsolationLevelStatement();
stmt.setGlobal(global);
if (identifierEquals("READ")) {
lexer.nextToken();
if (identifierEquals("UNCOMMITTED")) {
stmt.setLevel("READ UNCOMMITTED");
lexer.nextToken();
} else if (identifierEquals("WRITE")) {
stmt.setLevel("READ WRITE");
lexer.nextToken();
} else if (identifierEquals("ONLY")) {
stmt.setLevel("READ ONLY");
lexer.nextToken();
} else if (identifierEquals("COMMITTED")) {
stmt.setLevel("READ COMMITTED");
lexer.nextToken();
} else {
throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal());
}
} else if (identifierEquals("SERIALIZABLE")) {
stmt.setLevel("SERIALIZABLE");
lexer.nextToken();
} else if (identifierEquals("REPEATABLE")) {
lexer.nextToken();
if (identifierEquals("READ")) {
stmt.setLevel("REPEATABLE READ");
lexer.nextToken();
} else {
throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal());
}
} else {
throw new ParserException("UNKOWN TRANSACTION LEVEL : " + lexer.stringVal());
}
return stmt;
} else {
SQLSetStatement stmt = new SQLSetStatement();
parseAssignItems(stmt.getItems());
if (global != null && global.booleanValue()) {
SQLVariantRefExpr varRef = (SQLVariantRefExpr) stmt.getItems().get(0).getTarget();
varRef.setGlobal(true);
}
return stmt;
}
}
}
@@ -43,6 +43,7 @@ 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.MySqlSelectGroupBy;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetTransactionIsolationLevelStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatement;
@@ -206,4 +207,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
boolean visit(MySqlUpdateStatement x);
void endVisit(MySqlUpdateStatement x);
boolean visit(MySqlSetTransactionIsolationLevelStatement x);
void endVisit(MySqlSetTransactionIsolationLevelStatement x);
}
@@ -30,6 +30,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement;
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.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetTransactionIsolationLevelStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatement;
@@ -444,4 +445,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements
}
@Override
public boolean visit(MySqlSetTransactionIsolationLevelStatement x) {
return true;
}
@Override
public void endVisit(MySqlSetTransactionIsolationLevelStatement x) {
}
}
@@ -62,6 +62,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSQLColumnDefinitio
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.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetTransactionIsolationLevelStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatement;
@@ -100,7 +101,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
if (x.getOrderBy() != null) {
x.getOrderBy().setParent(x);
}
print("SELECT ");
if (SQLSetQuantifier.ALL == x.getDistionOption()) print("ALL ");
@@ -425,7 +426,30 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
public boolean visit(SQLVariantRefExpr x) {
print(x.getName());
if (x.isGlobal()) {
print("@@global.");
} else {
if ((!x.getName().startsWith("@")) && (!x.getName().equals("?"))) {
print("@@");
}
}
for (int i = 0; i < x.getName().length(); ++i) {
char ch = x.getName().charAt(i);
if (ch == '\'') {
if (x.getName().startsWith("@@") && i == 2) {
print(ch);
} else if (x.getName().startsWith("@") && i == 1) {
print(ch);
} else if (i != 0 && i != x.getName().length() - 1) {
print("\\'");
} else {
print(ch);
}
} else {
print(ch);
}
}
String collate = (String) x.getAttribute("COLLATE");
if (collate != null) {
@@ -1250,12 +1274,12 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public boolean visit(UserSpecification x) {
x.getUser().accept(this);
if (x.getPassword() != null) {
print(" IDENTIFIED BY ");
x.getPassword().accept(this);
}
if (x.getAuthPlugin() != null) {
print(" IDENTIFIED WITH ");
x.getAuthPlugin().accept(this);
@@ -1265,7 +1289,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public void endVisit(MySqlDropUser x) {
}
@Override
@@ -1277,7 +1301,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
public void endVisit(MySqlDropTableStatement x) {
}
@Override
@@ -1286,14 +1310,14 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
if (x.isIfExists()) {
print("IF EXISTS ");
}
printAndAccept(x.getTableSources(), ", ");
return false;
}
@Override
public void endVisit(MySqlPartitionByKey x) {
}
@Override
@@ -1301,7 +1325,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
print("PARTITION BY KEY (");
printAndAccept(x.getColumns(), ", ");
print(")");
if (x.getPartitionCount() != null) {
print(" PARTITIONS ");
x.getPartitionCount().accept(this);
@@ -1311,21 +1335,20 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
@Override
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) {
if (x.getColumnsTerminatedBy() != null || x.getColumnsEnclosedBy() != null || x.getColumnsEscaped() != null) {
print(" COLUMNS");
if (x.getColumnsTerminatedBy() != null) {
print(" TERMINATED BY ");
@@ -1358,39 +1381,56 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
x.getLinesTerminatedBy().accept(this);
}
}
return false;
}
@Override
public void endVisit(MySqlOutFileExpr x) {
}
@Override
public boolean visit(MySqlDescribeStatement x) {
print("DESCRIBE ");
print("DESC ");
x.getObject().accept(this);
return false;
}
@Override
public void endVisit(MySqlDescribeStatement x) {
}
@Override
public boolean visit(MySqlUpdateStatement x) {
super.visit((SQLUpdateStatement) x);
if (x.getLimit() != null) {
println();
x.getLimit().accept(this);
}
return false;
}
@Override
public boolean visit(MySqlUpdateStatement x) {
super.visit((SQLUpdateStatement) x);
if (x.getLimit() != null) {
println();
x.getLimit().accept(this);
}
return false;
}
@Override
public void endVisit(MySqlUpdateStatement x) {
}
@Override
public void endVisit(MySqlUpdateStatement x) {
}
@Override
public boolean visit(MySqlSetTransactionIsolationLevelStatement x) {
return false;
}
@Override
public void endVisit(MySqlSetTransactionIsolationLevelStatement x) {
if (x.getGlobal() == null) {
print("SET TRANSACTION ISOLATION LEVEL ");
} else if (x.getGlobal().booleanValue()) {
print("SET GLOBAL TRANSACTION ISOLATION LEVEL ");
} else {
print("SET SESSION TRANSACTION ISOLATION LEVEL ");
}
print(x.getLevel());
}
}
@@ -39,6 +39,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRollbackStatement;
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.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetTransactionIsolationLevelStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowColumnsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowDatabasesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatement;
@@ -505,4 +506,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
public void endVisit(MySqlUpdateStatement x) {
}
@Override
public boolean visit(MySqlSetTransactionIsolationLevelStatement x) {
return false;
}
@Override
public void endVisit(MySqlSetTransactionIsolationLevelStatement x) {
}
}
@@ -15,11 +15,12 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleDateExpr extends SQLLiteralExpr implements OracleExpr {
public class OracleDateExpr extends SQLExprImpl implements SQLLiteralExpr, OracleExpr {
private static final long serialVersionUID = 1L;
@@ -16,11 +16,12 @@
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleIntervalExpr extends SQLLiteralExpr implements OracleExpr {
public class OracleIntervalExpr extends SQLExprImpl implements SQLLiteralExpr, OracleExpr {
private static final long serialVersionUID = 1L;
private SQLExpr value;
@@ -15,11 +15,12 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.expr;
import com.alibaba.druid.sql.ast.SQLExprImpl;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleTimestampExpr extends SQLLiteralExpr implements OracleExpr {
public class OracleTimestampExpr extends SQLExprImpl implements SQLLiteralExpr, OracleExpr {
private static final long serialVersionUID = 1L;
private String literal;
@@ -55,6 +55,7 @@ import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.NotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey;
@@ -195,8 +196,16 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
break;
case VARIANT:
sqlExpr = new SQLVariantRefExpr(lexer.stringVal());
SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(lexer.stringVal());
lexer.nextToken();
if (varRefExpr.getName().equals("@") && lexer.token() == Token.LITERAL_CHARS) {
varRefExpr.setName("@'" + lexer.stringVal() + "'");
lexer.nextToken();
} else if (varRefExpr.getName().equals("@@") && lexer.token() == Token.LITERAL_CHARS) {
varRefExpr.setName("@@'" + lexer.stringVal() + "'");
lexer.nextToken();
}
sqlExpr = varRefExpr;
break;
case DEFAULT:
sqlExpr = new SQLDefaultExpr();
@@ -473,10 +482,6 @@ public class SQLExprParser extends SQLParser {
expr = dotRest(expr);
return primaryRest(expr);
} else if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
SQLExpr rightExp = primary();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp);
} else {
if (lexer.token() == Token.LPAREN) {
return methodRest(expr, true);
@@ -779,6 +784,10 @@ public class SQLExprParser extends SQLParser {
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp);
} else if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
rightExp = expr();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp);
}
return expr;
@@ -920,40 +929,40 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = bitOr();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThan, rightExp);
// expr = relationalRest(expr);
// expr = relationalRest(expr);
} else if (lexer.token() == Token.LTEQ) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqual, rightExp);
} else if (lexer.token() == Token.LTEQGT) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrEqualOrGreaterThan, rightExp);
} else if (lexer.token() == Token.GT) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThan, rightExp);
} else if (lexer.token() == Token.GTEQ) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.GreaterThanOrEqual, rightExp);
} else if (lexer.token() == Token.BANGLT) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotLessThan, rightExp);
} else if (lexer.token() == Token.BANGGT) {
@@ -967,14 +976,14 @@ public class SQLExprParser extends SQLParser {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.LessThanOrGreater, rightExp);
} else if (lexer.token() == Token.LIKE) {
lexer.nextToken();
rightExp = bitOr();
// rightExp = relationalRest(rightExp);
// rightExp = relationalRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Like, rightExp);
@@ -1168,4 +1177,23 @@ public class SQLExprParser extends SQLParser {
public SQLPrimaryKey parsePrimaryKey() {
throw new ParserException("TODO");
}
public SQLAssignItem parseAssignItem() {
SQLAssignItem item = new SQLAssignItem();
SQLExpr var = primary();
if (var instanceof SQLIdentifierExpr) {
var = new SQLVariantRefExpr(((SQLIdentifierExpr) var).getName());
}
item.setTarget(var);
if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
} else {
accept(Token.EQ);
}
item.setValue(expr());
return item;
}
}
@@ -124,6 +124,13 @@ public class SQLParser {
}
}
public void match(Token token) {
if (lexer.token() != token) {
throw new SQLParseException("syntax error, expect " + token + ", actual " + lexer.token() + " "
+ lexer.stringVal());
}
}
private int errorEndPos = -1;
protected void setErrorEndPos(int errPos) {
@@ -131,4 +138,5 @@ public class SQLParser {
errorEndPos = errPos;
}
}
}
@@ -294,11 +294,7 @@ public class SQLStatementParser extends SQLParser {
public void parseAssignItems(List<SQLAssignItem> items) {
for (;;) {
SQLAssignItem item = new SQLAssignItem();
item.setTarget(exprParser.primary());
accept(Token.EQ);
item.setValue(exprParser.expr());
SQLAssignItem item = exprParser.parseAssignItem();
items.add(item);
if (lexer.token() == Token.COMMA) {
@@ -310,6 +306,7 @@ public class SQLStatementParser extends SQLParser {
}
}
public SQLStatement parseCreate() throws ParserException {
char mark_ch = lexer.current();
int mark_bp = lexer.bp();
@@ -0,0 +1,112 @@
/*
* Copyright 1999-2002,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.util;
/**
* format validation
*
* This class encodes/decodes hexadecimal data
*
* @xerces.internal
*
* @author Jeffrey Rodriguez
* @version $Id: HexBin.java,v 1.4 2007/07/19 04:38:32 ofung Exp $
*/
public final class HexBin {
static private final int BASELENGTH = 128;
static private final int LOOKUPLENGTH = 16;
static final private byte [] hexNumberTable = new byte[BASELENGTH];
static final private char [] lookUpHexAlphabet = new char[LOOKUPLENGTH];
static {
for (int i = 0; i < BASELENGTH; i++ ) {
hexNumberTable[i] = -1;
}
for ( int i = '9'; i >= '0'; i--) {
hexNumberTable[i] = (byte) (i-'0');
}
for ( int i = 'F'; i>= 'A'; i--) {
hexNumberTable[i] = (byte) ( i-'A' + 10 );
}
for ( int i = 'f'; i>= 'a'; i--) {
hexNumberTable[i] = (byte) ( i-'a' + 10 );
}
for(int i = 0; i<10; i++ ) {
lookUpHexAlphabet[i] = (char)('0'+i);
}
for(int i = 10; i<=15; i++ ) {
lookUpHexAlphabet[i] = (char)('A'+i -10);
}
}
/**
* Encode a byte array to hex string
*
* @param binaryData array of byte to encode
* @return return encoded string
*/
static public String encode(byte[] binaryData) {
if (binaryData == null)
return null;
int lengthData = binaryData.length;
int lengthEncode = lengthData * 2;
char[] encodedData = new char[lengthEncode];
int temp;
for (int i = 0; i < lengthData; i++) {
temp = binaryData[i];
if (temp < 0)
temp += 256;
encodedData[i*2] = lookUpHexAlphabet[temp >> 4];
encodedData[i*2+1] = lookUpHexAlphabet[temp & 0xf];
}
return new String(encodedData);
}
/**
* Decode hex string to a byte array
*
* @param encoded encoded string
* @return return array of byte to encode
*/
static public byte[] decode(String encoded) {
if (encoded == null)
return null;
int lengthData = encoded.length();
if (lengthData % 2 != 0)
return null;
char[] binaryData = encoded.toCharArray();
int lengthDecode = lengthData / 2;
byte[] decodedData = new byte[lengthDecode];
byte temp1, temp2;
char tempChar;
for( int i = 0; i<lengthDecode; i++ ){
tempChar = binaryData[i*2];
temp1 = (tempChar < BASELENGTH) ? hexNumberTable[tempChar] : -1;
if (temp1 == -1)
return null;
tempChar = binaryData[i*2+1];
temp2 = (tempChar < BASELENGTH) ? hexNumberTable[tempChar] : -1;
if (temp2 == -1)
return null;
decodedData[i] = (byte)((temp1 << 4) | temp2);
}
return decodedData;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
/**
* (created at 2011-11-11)
*/
package com.alibaba.druid.bvt.sql.cobar;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.expr.SQLHexExpr;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
/**
* @author <a href="mailto:shuo.qius@alibaba-inc.com">QIU Shuo</a>
*/
public class LiteralHexadecimalTest extends TestCase {
public void test_0() throws Exception {
String sql = "x'E982B1E7A195275C73'";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("邱硕'\\s", new String(hex.toBytes(), "utf-8"));
}
public void test_1() throws Exception {
String sql = "x'0D0A'";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("\r\n", new String(hex.toBytes(), "utf-8"));
}
public void test_2() throws Exception {
String sql = "X'4D7953514C'";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("MySQL", new String(hex.toBytes(), "utf-8"));
}
public void test_3() throws Exception {
String sql = "0x5061756c";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("Paul", new String(hex.toBytes(), "utf-8"));
}
public void test_4() throws Exception {
String sql = "0x41";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("A", new String(hex.toBytes(), "utf-8"));
}
public void test_5() throws Exception {
String sql = "0x636174";
SQLHexExpr hex = (SQLHexExpr) new MySqlExprParser(sql).expr();
Assert.assertEquals("cat", new String(hex.toBytes(), "utf-8"));
}
}