Merge pull request #954 from zhujunxxxxx/master

增加mysql对procedure语法的识别
This commit is contained in:
高铁
2015-09-12 23:34:30 +08:00
19 changed files with 2203 additions and 4 deletions
@@ -0,0 +1,103 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql procedure case statement
* @author zz
*
*/
public class MySqlCaseStatement extends MySqlStatementImpl{
//case expr
private SQLExpr condition;
//when statement list
private List<MySqlWhenfStatement> whenList=new ArrayList<MySqlCaseStatement.MySqlWhenfStatement>();
//else statement
private MySqlElseStatement elseItem;
public SQLExpr getCondition() {
return condition;
}
public void setCondition(SQLExpr condition) {
this.condition = condition;
}
public List<MySqlWhenfStatement> getWhenList() {
return whenList;
}
public void setWhenList(List<MySqlWhenfStatement> whenList) {
this.whenList = whenList;
}
public void addWhenStatement(MySqlWhenfStatement stmt)
{
this.whenList.add(stmt);
}
public MySqlElseStatement getElseItem() {
return elseItem;
}
public void setElseItem(MySqlElseStatement elseItem) {
this.elseItem = elseItem;
}
@Override
public void accept0(MySqlASTVisitor visitor) {
// TODO Auto-generated method stub
if (visitor.visit(this)) {
acceptChild(visitor, condition);
acceptChild(visitor, whenList);
acceptChild(visitor, elseItem);
}
visitor.endVisit(this);
}
/**
* case when statement
* @author zz
*
*/
public static class MySqlWhenfStatement extends MySqlObjectImpl {
private SQLExpr condition;
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, condition);
acceptChild(visitor, statements);
}
visitor.endVisit(this);
}
public SQLExpr getCondition() {
return condition;
}
public void setCondition(SQLExpr condition) {
this.condition = condition;
}
public List<SQLStatement> getStatements() {
return statements;
}
public void setStatements(List<SQLStatement> statements) {
this.statements = statements;
}
}
}
@@ -0,0 +1,64 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBlockStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql create procedure statement
* @author zz
*
*/
public class MySqlCreateProcedureStatement extends MySqlStatementImpl {
private boolean orReplace;
private SQLName name;
private MySqlBlockStatement block;
private List<MySqlParameter> parameters = new ArrayList<MySqlParameter>();
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, name);
acceptChild(visitor, parameters);
acceptChild(visitor, block);
}
visitor.endVisit(this);
}
public List<MySqlParameter> getParameters() {
return parameters;
}
public void setParameters(List<MySqlParameter> parameters) {
this.parameters = parameters;
}
public SQLName getName() {
return name;
}
public void setName(SQLName name) {
this.name = name;
}
public MySqlBlockStatement getBlock() {
return block;
}
public void setBlock(MySqlBlockStatement block) {
this.block = block;
}
public boolean isOrReplace() {
return orReplace;
}
public void setOrReplace(boolean orReplace) {
this.orReplace = orReplace;
}
}
@@ -0,0 +1,55 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql declare statement
* @author sei.zz
*
*/
public class MySqlDeclareStatement extends MySqlStatementImpl{
//var type
private SQLDataType type;
//var list
private List<SQLExpr> varList=new ArrayList<SQLExpr>();
public List<SQLExpr> getVarList() {
return varList;
}
public void addVar(SQLExpr expr)
{
varList.add(expr);
}
public void setVarList(List<SQLExpr> varList) {
this.varList = varList;
}
public SQLDataType getType() {
return type;
}
public void setType(SQLDataType type) {
this.type = type;
}
@Override
public void accept0(MySqlASTVisitor visitor) {
// TODO Auto-generated method stub
if (visitor.visit(this)) {
acceptChild(visitor, type);
acceptChild(visitor, varList);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,35 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql procedure else statement
* @author zz
*
*/
public class MySqlElseStatement extends MySqlObjectImpl {
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, statements);
}
visitor.endVisit(this);
}
public List<SQLStatement> getStatements() {
return statements;
}
public void setStatements(List<SQLStatement> statements) {
this.statements = statements;
}
}
@@ -0,0 +1,95 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql procedure if statement
* @author sei.zz
*
*/
public class MySqlIfStatement extends MySqlStatementImpl{
private SQLExpr condition;
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
private List<MySqlElseIfStatement> elseIfList = new ArrayList<MySqlElseIfStatement>();
private MySqlElseStatement elseItem;
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, condition);
acceptChild(visitor, statements);
acceptChild(visitor, elseIfList);
acceptChild(visitor, elseItem);
}
visitor.endVisit(this);
}
public SQLExpr getCondition() {
return condition;
}
public void setCondition(SQLExpr condition) {
this.condition = condition;
}
public List<SQLStatement> getStatements() {
return statements;
}
public void setStatements(List<SQLStatement> statements) {
this.statements = statements;
}
public List<MySqlElseIfStatement> getElseIfList() {
return elseIfList;
}
public void setElseIfList(List<MySqlElseIfStatement> elseIfList) {
this.elseIfList = elseIfList;
}
public MySqlElseStatement getElseItem() {
return elseItem;
}
public void setElseItem(MySqlElseStatement elseItem) {
this.elseItem = elseItem;
}
/**
* comment: else if语句
* @author sei.zz
*
*/
public static class MySqlElseIfStatement extends MySqlObjectImpl {
private SQLExpr condition;
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, condition);
acceptChild(visitor, statements);
}
visitor.endVisit(this);
}
public SQLExpr getCondition() {
return condition;
}
public void setCondition(SQLExpr condition) {
this.condition = condition;
}
public List<SQLStatement> getStatements() {
return statements;
}
public void setStatements(List<SQLStatement> statements) {
this.statements = statements;
}
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 1999-2101 Alibaba Group Holding Ltd.
*
* 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.sql.dialect.mysql.ast.clause;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* MySql procedure parameter
* @author sei.zz
*
*/
public class MySqlParameter extends MySqlObjectImpl {
private SQLExpr name;
private SQLDataType dataType;
private SQLExpr defaultValue;
public SQLExpr getDefaultValue() {
return defaultValue;
}
public void setDefaultValue(SQLExpr deaultValue) {
this.defaultValue = deaultValue;
}
public SQLExpr getName() {
return name;
}
public void setName(SQLExpr name) {
this.name = name;
}
public SQLDataType getDataType() {
return dataType;
}
public void setDataType(SQLDataType dataType) {
this.dataType = dataType;
}
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, name);
acceptChild(visitor, dataType);
acceptChild(visitor, defaultValue);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,51 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
import com.alibaba.druid.sql.ast.SQLExpr;
/**
* MySql procedure select into statement
* @author sei.zz
*
*/
public class MySqlSelectIntoStatement extends MySqlStatementImpl{
//select statement
private SQLSelect select;
//var list
private List<SQLExpr> varList=new ArrayList<SQLExpr>();
public SQLSelect getSelect() {
return select;
}
public void setSelect(SQLSelect select) {
this.select = select;
}
public List<SQLExpr> getVarList() {
return varList;
}
public void setVarList(List<SQLExpr> varList) {
this.varList = varList;
}
@Override
public void accept0(MySqlASTVisitor visitor) {
// TODO Auto-generated method stub
if (visitor.visit(this)) {
acceptChild(visitor, select);
acceptChild(visitor, varList);
}
visitor.endVisit(this);
}
}
@@ -0,0 +1,60 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBlockStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
/**
* MySql procedure statement type
* @author zz
*
*/
public enum MySqlStatementType {
//select statement
SELECT(SQLSelectStatement.class.getName()),
//update statement
UPDATE(MySqlUpdateStatement.class.getName()),
//insert statement
INSERT(MySqlInsertStatement.class.getName()),
//delete statement
DELETE(MySqlDeleteStatement.class.getName()),
//while statement
WHILE(MySqlWhileStatement.class.getName()),
//if statement
IF(MySqlIfStatement.class.getName()),
//begin-end
BLOCK(MySqlBlockStatement.class.getName()),
//declare statement
DECLARE(MySqlDeclareStatement.class.getName()),
//select into
SELECTINTO(MySqlSelectIntoStatement.class.getName()),
//case
CASE(MySqlCaseStatement.class.getName()),
UNDEFINED,
;
public final String name;
MySqlStatementType(){
this(null);
}
MySqlStatementType(String name){
this.name = name;
}
public static MySqlStatementType getType(SQLStatement stmt)
{
for (MySqlStatementType type : MySqlStatementType.values()) {
if (type.name == stmt.getClass().getName()) {
return type;
}
}
return UNDEFINED;
}
}
@@ -0,0 +1,46 @@
package com.alibaba.druid.sql.dialect.mysql.ast.clause;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatementImpl;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
/**
* comment: 存储过程中while循环语句
* @author 小竹zz
*
*/
public class MySqlWhileStatement extends MySqlStatementImpl {
//while循环的表达式
private SQLExpr condition;
private List<SQLStatement> statements = new ArrayList<SQLStatement>();
@Override
public void accept0(MySqlASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, condition);
acceptChild(visitor, statements);
}
visitor.endVisit(this);
}
public List<SQLStatement> getStatements() {
return statements;
}
public void setStatements(List<SQLStatement> statements) {
this.statements = statements;
}
public SQLExpr getCondition() {
return condition;
}
public void setCondition(SQLExpr condition) {
this.condition = condition;
}
}
@@ -0,0 +1,75 @@
package com.alibaba.druid.sql.dialect.mysql.executor;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLStatement;
/**
* comment: mysql存储过程执行器
* @author sei.zz
*
*/
public class MySqlProcedureExecutor {
public static int executeStatements(List<SQLStatement> list)
{
return 0;
}
public static int executeStatement(SQLStatement stmt)
{
return 0;
}
public static int executeIf(SQLStatement stmt)
{
return 0;
}
public static int executeWhile(SQLStatement stmt)
{
return 0;
}
public static int executeLoop(SQLStatement stmt)
{
return 0;
}
public static int executeCase(SQLStatement stmt)
{
return 0;
}
public static int executeAssign(SQLStatement stmt)
{
return 0;
}
public static int executeOpen(SQLStatement stmt)
{
return 0;
}
public static int executeFetch(SQLStatement stmt)
{
return 0;
}
public static int executeClose(SQLStatement stmt)
{
return 0;
}
public static int executeSQL(SQLStatement stmt)
{
return 0;
}
public static int executeFunction(SQLStatement stmt)
{
return 0;
}
}
@@ -0,0 +1,402 @@
/*
* Copyright 1999-2101 Alibaba Group Holding Ltd.
*
* 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.sql.dialect.mysql.parser;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
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.MySqlForceIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIgnoreIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIndexHintImpl;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
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.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
/**
* parse select into statement
* @author sei.zz
*
*/
public class MySqlSelectIntoParser extends SQLSelectParser {
private List<SQLExpr> argsList;
public MySqlSelectIntoParser(SQLExprParser exprParser){
super(exprParser);
}
public MySqlSelectIntoParser(String sql){
this(new MySqlExprParser(sql));
}
public MySqlSelectIntoStatement parseSelectInto()
{
SQLSelect select=select();
MySqlSelectIntoStatement stmt=new MySqlSelectIntoStatement();
stmt.setSelect(select);
stmt.setVarList(argsList);
return stmt;
}
@Override
public SQLSelectQuery query() {
if (lexer.token() == (Token.LPAREN)) {
lexer.nextToken();
SQLSelectQuery select = query();
accept(Token.RPAREN);
return queryRest(select);
}
MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();
if (lexer.token() == Token.SELECT) {
lexer.nextToken();
if (lexer.token() == Token.HINT) {
this.exprParser.parseHints(queryBlock.getHints());
}
if (lexer.token() == Token.COMMENT) {
lexer.nextToken();
}
if (lexer.token() == (Token.DISTINCT)) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
lexer.nextToken();
} else if (identifierEquals("DISTINCTROW")) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCTROW);
lexer.nextToken();
} else if (lexer.token() == (Token.ALL)) {
queryBlock.setDistionOption(SQLSetQuantifier.ALL);
lexer.nextToken();
}
if (identifierEquals("HIGH_PRIORITY")) {
queryBlock.setHignPriority(true);
lexer.nextToken();
}
if (identifierEquals("STRAIGHT_JOIN")) {
queryBlock.setStraightJoin(true);
lexer.nextToken();
}
if (identifierEquals("SQL_SMALL_RESULT")) {
queryBlock.setSmallResult(true);
lexer.nextToken();
}
if (identifierEquals("SQL_BIG_RESULT")) {
queryBlock.setBigResult(true);
lexer.nextToken();
}
if (identifierEquals("SQL_BUFFER_RESULT")) {
queryBlock.setBufferResult(true);
lexer.nextToken();
}
if (identifierEquals("SQL_CACHE")) {
queryBlock.setCache(true);
lexer.nextToken();
}
if (identifierEquals("SQL_NO_CACHE")) {
queryBlock.setCache(false);
lexer.nextToken();
}
if (identifierEquals("SQL_CALC_FOUND_ROWS")) {
queryBlock.setCalcFoundRows(true);
lexer.nextToken();
}
parseSelectList(queryBlock);
argsList=parseIntoArgs();
}
parseFrom(queryBlock);
parseWhere(queryBlock);
parseGroupBy(queryBlock);
queryBlock.setOrderBy(this.exprParser.parseOrderBy());
if (lexer.token() == Token.LIMIT) {
queryBlock.setLimit(parseLimit());
}
if (lexer.token() == Token.PROCEDURE) {
lexer.nextToken();
throw new ParserException("TODO");
}
parseInto(queryBlock);
if (lexer.token() == Token.FOR) {
lexer.nextToken();
accept(Token.UPDATE);
queryBlock.setForUpdate(true);
}
if (lexer.token() == Token.LOCK) {
lexer.nextToken();
accept(Token.IN);
acceptIdentifier("SHARE");
acceptIdentifier("MODE");
queryBlock.setLockInShareMode(true);
}
return queryRest(queryBlock);
}
protected List<SQLExpr> parseIntoArgs() {
List<SQLExpr> args=new ArrayList<SQLExpr>();
if (lexer.token() == (Token.INTO)) {
accept(Token.INTO);
//lexer.nextToken();
for (;;) {
SQLExpr var = exprParser.primary();
if (var instanceof SQLIdentifierExpr) {
var = new SQLVariantRefExpr(
((SQLIdentifierExpr) var).getName());
}
args.add(var);
if (lexer.token() == Token.COMMA) {
accept(Token.COMMA);
continue;
}
else
{
break;
}
}
}
return args;
}
protected void parseInto(SQLSelectQueryBlock queryBlock) {
if (lexer.token() == (Token.INTO)) {
lexer.nextToken();
if (identifierEquals("OUTFILE")) {
lexer.nextToken();
MySqlOutFileExpr outFile = new MySqlOutFileExpr();
outFile.setFile(expr());
queryBlock.setInto(outFile);
if (identifierEquals("FIELDS") || identifierEquals("COLUMNS")) {
lexer.nextToken();
if (identifierEquals("TERMINATED")) {
lexer.nextToken();
accept(Token.BY);
}
outFile.setColumnsTerminatedBy((SQLLiteralExpr) expr());
if (identifierEquals("OPTIONALLY")) {
lexer.nextToken();
outFile.setColumnsEnclosedOptionally(true);
}
if (identifierEquals("ENCLOSED")) {
lexer.nextToken();
accept(Token.BY);
outFile.setColumnsEnclosedBy((SQLLiteralExpr) expr());
}
if (identifierEquals("ESCAPED")) {
lexer.nextToken();
accept(Token.BY);
outFile.setColumnsEscaped((SQLLiteralExpr) expr());
}
}
if (identifierEquals("LINES")) {
lexer.nextToken();
if (identifierEquals("STARTING")) {
lexer.nextToken();
accept(Token.BY);
outFile.setLinesStartingBy((SQLLiteralExpr) expr());
} else {
identifierEquals("TERMINATED");
lexer.nextToken();
accept(Token.BY);
outFile.setLinesTerminatedBy((SQLLiteralExpr) expr());
}
}
} else {
queryBlock.setInto(this.exprParser.name());
}
}
}
protected void parseGroupBy(SQLSelectQueryBlock queryBlock) {
SQLSelectGroupByClause groupBy = null;
if (lexer.token() == Token.GROUP) {
groupBy = new SQLSelectGroupByClause();
lexer.nextToken();
accept(Token.BY);
while (true) {
groupBy.addItem(this.getExprParser().parseSelectGroupByItem());
if (!(lexer.token() == (Token.COMMA))) {
break;
}
lexer.nextToken();
}
if (lexer.token() == Token.WITH) {
lexer.nextToken();
acceptIdentifier("ROLLUP");
MySqlSelectGroupBy mySqlGroupBy = new MySqlSelectGroupBy();
for (SQLExpr sqlExpr : groupBy.getItems()) {
mySqlGroupBy.addItem(sqlExpr);
}
mySqlGroupBy.setRollUp(true);
groupBy = mySqlGroupBy;
}
}
if (lexer.token() == Token.HAVING) {
lexer.nextToken();
if (groupBy == null) {
groupBy = new SQLSelectGroupByClause();
}
groupBy.setHaving(this.exprParser.expr());
}
queryBlock.setGroupBy(groupBy);
}
protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {
if (identifierEquals("USING")) {
return tableSource;
}
if (lexer.token() == Token.USE) {
lexer.nextToken();
MySqlUseIndexHint hint = new MySqlUseIndexHint();
parseIndexHint(hint);
tableSource.getHints().add(hint);
}
if (identifierEquals("IGNORE")) {
lexer.nextToken();
MySqlIgnoreIndexHint hint = new MySqlIgnoreIndexHint();
parseIndexHint(hint);
tableSource.getHints().add(hint);
}
if (identifierEquals("FORCE")) {
lexer.nextToken();
MySqlForceIndexHint hint = new MySqlForceIndexHint();
parseIndexHint(hint);
tableSource.getHints().add(hint);
}
return super.parseTableSourceRest(tableSource);
}
private void parseIndexHint(MySqlIndexHintImpl hint) {
if (lexer.token() == Token.INDEX) {
lexer.nextToken();
} else {
accept(Token.KEY);
}
if (lexer.token() == Token.FOR) {
lexer.nextToken();
if (lexer.token() == Token.JOIN) {
lexer.nextToken();
hint.setOption(MySqlIndexHint.Option.JOIN);
} else if (lexer.token() == Token.ORDER) {
lexer.nextToken();
accept(Token.BY);
hint.setOption(MySqlIndexHint.Option.ORDER_BY);
} else {
accept(Token.GROUP);
accept(Token.BY);
hint.setOption(MySqlIndexHint.Option.GROUP_BY);
}
}
accept(Token.LPAREN);
if (lexer.token() == Token.PRIMARY) {
lexer.nextToken();
hint.getIndexList().add(new SQLIdentifierExpr("PRIMARY"));
} else {
this.exprParser.names(hint.getIndexList());
}
accept(Token.RPAREN);
}
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 ((MySqlExprParser) this.exprParser).parseLimit();
}
public MySqlExprParser getExprParser() {
return (MySqlExprParser) exprParser;
}
}
@@ -19,11 +19,15 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
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.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
@@ -57,6 +61,16 @@ 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.MysqlForeignKey;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlElseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement.MySqlElseIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlParameter;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableAddColumn;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn;
@@ -358,6 +372,13 @@ public class MySqlStatementParser extends SQLStatementParser {
}
return parseCreateTrigger();
}
//parse create procedure
if (lexer.token() == Token.PROCEDURE) {
if (replace) {
lexer.reset(markBp, markChar, Token.CREATE);
}
return parseCreateProcedure();
}
throw new ParserException("TODO " + lexer.token());
}
@@ -694,8 +715,8 @@ public class MySqlStatementParser extends SQLStatementParser {
accept(Token.BEGIN);
parseStatementList(block.getStatementList());
//parseStatementList(block.getStatementList());
parseProcedureStatementList(block.getStatementList());
accept(Token.END);
return block;
@@ -2705,6 +2726,418 @@ public class MySqlStatementParser extends SQLStatementParser {
MySqlHintStatement stmt = new MySqlHintStatement();
stmt.setHints(this.exprParser.parseHints());
return stmt;
}
return stmt;
}
/**
* parse create procedure statement
*/
public MySqlCreateProcedureStatement parseCreateProcedure() {
/**
* CREATE OR REPALCE PROCEDURE SP_NAME(parameter_list) BEGIN block_statement END
*/
MySqlCreateProcedureStatement stmt = new MySqlCreateProcedureStatement();
accept(Token.CREATE);
if (lexer.token() == Token.OR) {
lexer.nextToken();
accept(Token.REPLACE);
stmt.setOrReplace(true);
}
accept(Token.PROCEDURE);
stmt.setName(this.exprParser.name());
if (lexer.token() == Token.LPAREN) {// match "("
lexer.nextToken();
parserParameters(stmt.getParameters());
accept(Token.RPAREN);// match ")"
}
MySqlBlockStatement block = this.parseBlock();
stmt.setBlock(block);
return stmt;
}
/**
* parse create procedure parameters
* @param parameters
*/
private void parserParameters(List<MySqlParameter> parameters) {
for (;;) {
MySqlParameter parameter = new MySqlParameter();
if (lexer.token() == Token.CURSOR) {
lexer.nextToken();
parameter.setName(this.exprParser.name());
accept(Token.IS);
SQLSelect select = this.createSQLSelectParser().select();
SQLDataTypeImpl dataType = new SQLDataTypeImpl();
dataType.setName("CURSOR");
parameter.setDataType(dataType);
parameter.setDefaultValue(new SQLQueryExpr(select));
} else {
parameter.setName(this.exprParser.name());
parameter.setDataType(this.exprParser.parseDataType());
if (lexer.token() == Token.COLONEQ) {
lexer.nextToken();
parameter.setDefaultValue(this.exprParser.expr());
}
}
parameters.add(parameter);
if (lexer.token() == Token.COMMA || lexer.token() == Token.SEMI) {
lexer.nextToken();
}
if (lexer.token() != Token.BEGIN && lexer.token() != Token.RPAREN) {
continue;
}
break;
}
}
/**
* parse procedure statement block
* @param statementList
*/
private void parseProcedureStatementList(List<SQLStatement> statementList)
{
parseProcedureStatementList(statementList,-1);
}
/**
* parse procedure statement block
*/
private void parseProcedureStatementList(List<SQLStatement> statementList, int max) {
for (;;) {
if (max != -1) {
if (statementList.size() >= max) {
return;
}
}
if (lexer.token() == Token.EOF) {
return;
}
if (lexer.token() == Token.END) {
return;
}
if (lexer.token() == Token.ELSE) {
return;
}
if (lexer.token() == (Token.SEMI)) {
lexer.nextToken();
continue;
}
if (lexer.token() == Token.WHEN) {
return;
}
// select into
if (lexer.token() == (Token.SELECT)) {
statementList.add(this.parseSelectInto());
continue;
}
// update
if (lexer.token() == (Token.UPDATE)) {
statementList.add(parseUpdateStatement());
continue;
}
// create
if (lexer.token() == (Token.CREATE)) {
statementList.add(parseCreate());
continue;
}
// insert
if (lexer.token() == Token.INSERT) {
statementList.add(parseInsert());
continue;
}
// delete
if (lexer.token() == (Token.DELETE)) {
statementList.add(parseDeleteStatement());
continue;
}
// call
if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) {
statementList.add(this.parseCall());
continue;
}
// begin
if (lexer.token() == Token.BEGIN) {
statementList.add(this.parseBlock());
continue;
}
if (lexer.token() == Token.VARIANT) {
SQLExpr variant = this.exprParser.primary();
if (variant instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant;
if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) {
SQLSetStatement stmt = new SQLSetStatement(
binaryOpExpr.getLeft(),
binaryOpExpr.getRight(), getDbType());
statementList.add(stmt);
continue;
}
}
accept(Token.COLONEQ);
SQLExpr value = this.exprParser.expr();
SQLSetStatement stmt = new SQLSetStatement(variant, value,
getDbType());
statementList.add(stmt);
continue;
}
// select
if (lexer.token() == Token.LPAREN) {
char ch = lexer.current();
int bp = lexer.bp();
lexer.nextToken();
if (lexer.token() == Token.SELECT) {
lexer.reset(bp, ch, Token.LPAREN);
statementList.add(this.parseSelect());
continue;
} else {
throw new ParserException("TODO : " + lexer.token() + " "
+ lexer.stringVal());
}
}
// assign statement
if (lexer.token() == Token.SET) {
statementList.add(this.parseAssign());
continue;
}
// while statement
if (lexer.token() == Token.WHILE) {
statementList.add(this.parseWhile());
continue;
}
// if statement
if (lexer.token() == Token.IF) {
statementList.add(this.parseIf());
continue;
}
// case statement
if (lexer.token() == Token.CASE) {
statementList.add(this.parseCase());
continue;
}
// declare statement
if (lexer.token() == Token.DECLARE) {
statementList.add(this.parseDeclare());
continue;
}
throw new ParserException("TODO : " + lexer.token() + " "
+ lexer.stringVal());
}
}
/**
* parse if statement
* @return MySqlIfStatement
*/
public MySqlIfStatement parseIf() {
accept(Token.IF);
MySqlIfStatement stmt = new MySqlIfStatement();
stmt.setCondition(this.exprParser.expr());
accept(Token.THEN);
this.parseProcedureStatementList(stmt.getStatements());
while (lexer.token() == Token.ELSE) {
lexer.nextToken();
if (lexer.token() == Token.IF) {
lexer.nextToken();
MySqlElseIfStatement elseIf = new MySqlElseIfStatement();
elseIf.setCondition(this.exprParser.expr());
accept(Token.THEN);
this.parseProcedureStatementList(elseIf.getStatements());
stmt.getElseIfList().add(elseIf);
} else {
MySqlElseStatement elseItem = new MySqlElseStatement();
this.parseProcedureStatementList(elseItem.getStatements());
stmt.setElseItem(elseItem);
break;
}
}
accept(Token.END);
accept(Token.IF);
return stmt;
}
/**
* parse while statement
* @return MySqlWhileStatement
*/
public MySqlWhileStatement parseWhile() {
accept(Token.WHILE);
MySqlWhileStatement stmt = new MySqlWhileStatement();
stmt.setCondition(this.exprParser.expr());
accept(Token.DO);
this.parseProcedureStatementList(stmt.getStatements());
accept(Token.END);
accept(Token.WHILE);
return stmt;
}
/**
* parse case statement
* @return MySqlCaseStatement
*/
public MySqlCaseStatement parseCase()
{
MySqlCaseStatement stmt=new MySqlCaseStatement();
accept(Token.CASE);
if(lexer.token()==Token.WHEN)// grammar 1
{
while (lexer.token() == Token.WHEN) {
MySqlWhenfStatement when=new MySqlWhenfStatement();
//when expr
when.setCondition(exprParser.expr());
accept(Token.THEN);
//when block
parseProcedureStatementList(when.getStatements());
stmt.addWhenStatement(when);
}
if(lexer.token()==Token.ELSE)
{
//parse else block
MySqlElseStatement elseStmt=new MySqlElseStatement();
parseProcedureStatementList(elseStmt.getStatements());
stmt.setElseItem(elseStmt);
}
}
else// grammar 2
{
//case expr
stmt.setCondition(exprParser.expr());
while (lexer.token() == Token.WHEN) {
accept(Token.WHEN);
MySqlWhenfStatement when=new MySqlWhenfStatement();
//when expr
when.setCondition(exprParser.expr());
accept(Token.THEN);
//when block
parseProcedureStatementList(when.getStatements());
stmt.addWhenStatement(when);
}
if(lexer.token()==Token.ELSE)
{
accept(Token.ELSE);
//else block
MySqlElseStatement elseStmt=new MySqlElseStatement();
parseProcedureStatementList(elseStmt.getStatements());
stmt.setElseItem(elseStmt);
}
}
accept(Token.END);
accept(Token.CASE);
return stmt;
}
/**
* parse declare statement
*/
public MySqlDeclareStatement parseDeclare()
{
MySqlDeclareStatement stmt=new MySqlDeclareStatement();
accept(Token.DECLARE);
//lexer.nextToken();
for(;;)
{
SQLExpr var = exprParser.primary();
if (var instanceof SQLIdentifierExpr) {
var = new SQLVariantRefExpr(((SQLIdentifierExpr) var).getName());
}
stmt.addVar(var);
if(lexer.token()==Token.COMMA)
{
accept(Token.COMMA);
continue;
}
else if(lexer.token()!=Token.EOF)
{
//var type
stmt.setType(exprParser.parseDataType());
break;
}
else
{
setErrorEndPos(lexer.pos());
printError(lexer.token());
}
}
return stmt;
}
/**
* parse assign statement
*/
public SQLSetStatement parseAssign()
{
accept(Token.SET);
SQLSetStatement stmt = new SQLSetStatement(getDbType());
parseAssignItems(stmt.getItems(), stmt);
return stmt;
}
/**
* parse select into
*/
public MySqlSelectIntoStatement parseSelectInto()
{
MySqlSelectIntoParser parse=new MySqlSelectIntoParser(this.exprParser);
return parse.parseSelectInto();
}
}
@@ -22,6 +22,16 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlElseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement.MySqlElseIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlParameter;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr;
@@ -571,4 +581,48 @@ public interface MySqlASTVisitor extends SQLASTVisitor {
boolean visit(MySqlBlockStatement x);
void endVisit(MySqlBlockStatement x);
/**
* support procedure
*/
boolean visit(MySqlCreateProcedureStatement x);
void endVisit(MySqlCreateProcedureStatement x);
boolean visit(MySqlParameter x);
void endVisit(MySqlParameter x);
boolean visit(MySqlWhileStatement x);
void endVisit(MySqlWhileStatement x);
boolean visit(MySqlIfStatement x);
void endVisit(MySqlIfStatement x);
boolean visit(MySqlElseIfStatement x);
void endVisit(MySqlElseIfStatement x);
boolean visit(MySqlElseStatement x);
void endVisit(MySqlElseStatement x);
boolean visit(MySqlCaseStatement x);
void endVisit(MySqlCaseStatement x);
boolean visit(MySqlDeclareStatement x);
void endVisit(MySqlDeclareStatement x);
boolean visit(MySqlSelectIntoStatement x);
void endVisit(MySqlSelectIntoStatement x);
boolean visit(MySqlWhenfStatement x);
void endVisit(MySqlWhenfStatement x);
} //
@@ -22,6 +22,16 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlElseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement.MySqlElseIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlParameter;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr;
@@ -1268,4 +1278,128 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq
}
/**
* support procedure
*/
@Override
public boolean visit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlParameter x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlParameter x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlIfStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlElseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
}
//add:end
} //
@@ -26,6 +26,7 @@ import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
@@ -34,6 +35,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlForceIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlIgnoreIndexHint;
@@ -42,6 +44,16 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlElseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement.MySqlElseIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlParameter;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr;
@@ -3198,4 +3210,285 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV
}
/**
* comment: visit procedure node
* author ��zz
*/
@Override
public boolean visit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
if (x.isOrReplace()) {
print("CREATE OR REPLACE PROCEDURE ");
} else {
print("CREATE PROCEDURE ");
}
x.getName().accept(this);
int paramSize = x.getParameters().size();
if (paramSize > 0) {
print(" (");
incrementIndent();
println();
for (int i = 0; i < paramSize; ++i) {
if (i != 0) {
print(", ");
println();
}
MySqlParameter param = x.getParameters().get(i);
param.accept(this);
}
decrementIndent();
println();
print(")");
}
println();
x.getBlock().setParent(x);
x.getBlock().accept(this);
return false;
}
@Override
public void endVisit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlParameter x) {
// TODO Auto-generated method stub
if (x.getDataType().getName().equalsIgnoreCase("CURSOR")) {
print("CURSOR ");
x.getName().accept(this);
print(" IS");
incrementIndent();
println();
SQLSelect select = ((SQLQueryExpr) x.getDefaultValue()).getSubQuery();
select.accept(this);
decrementIndent();
} else {
x.getName().accept(this);
print(" ");
x.getDataType().accept(this);
if (x.getDefaultValue() != null) {
print(" := ");
x.getDefaultValue().accept(this);
}
}
return false;
}
@Override
public void endVisit(MySqlParameter x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
print("WHILE ");
x.getCondition().accept(this);
print(" DO");
println();
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
SQLStatement item = x.getStatements().get(i);
item.setParent(x);
item.accept(this);
if (i != size - 1) {
println();
}
}
println();
print("END WHILE");
return false;
}
@Override
public void endVisit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlIfStatement x) {
// TODO Auto-generated method stub
print("IF ");
x.getCondition().accept(this);
print(" THEN");
println();
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
SQLStatement item = x.getStatements().get(i);
item.setParent(x);
item.accept(this);
if (i != size - 1) {
println();
}
}
println();
for (MySqlElseIfStatement iterable_element : x.getElseIfList()) {
iterable_element.accept(this);
}
if(x.getElseItem()!=null)
x.getElseItem().accept(this);
print("END IF");
return false;
}
@Override
public void endVisit(MySqlIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
print("ELSE IF ");
x.getCondition().accept(this);
print(" THEN");
println();
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
SQLStatement item = x.getStatements().get(i);
item.setParent(x);
item.accept(this);
if (i != size - 1) {
println();
}
}
println();
return false;
}
@Override
public void endVisit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseStatement x) {
// TODO Auto-generated method stub
print("ELSE ");
println();
for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
SQLStatement item = x.getStatements().get(i);
item.setParent(x);
item.accept(this);
if (i != size - 1) {
println();
}
}
println();
return false;
}
@Override
public void endVisit(MySqlElseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
print("CASE ");
x.getCondition().accept(this);
println();
for (int i = 0; i < x.getWhenList().size(); i++) {
x.getWhenList().get(i).accept(this);
// if (i != x.getWhenList().size() - 1) {
// println();
// }
}
if(x.getElseItem()!=null)
x.getElseItem().accept(this);
print("END CASE");
return false;
}
@Override
public void endVisit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
print("DECLARE ");
for (int i = 0; i < x.getVarList().size(); i++) {
x.getVarList().get(i).accept(this);
if(i!=x.getVarList().size()-1)
print(",");
}
print(" ");
x.getType().accept(this);
return false;
}
@Override
public void endVisit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
x.getSelect().accept(this);
print(" INTO ");
for (int i = 0; i < x.getVarList().size(); i++) {
x.getVarList().get(i).accept(this);
if(i!=x.getVarList().size()-1)
print(",");
//println(x.getVarList().get(i).toString());
}
return false;
}
@Override
public void endVisit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
print("WHEN ");
x.getCondition().accept(this);
println(" THEN");
for (int i = 0; i < x.getStatements().size(); i++) {
x.getStatements().get(i).accept(this);
if (i != x.getStatements().size() - 1) {
println();
}
}
println();
return false;
}
@Override
public void endVisit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
}
} //
@@ -37,6 +37,16 @@ import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUseIndexHint;
import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlCreateProcedureStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlElseStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlIfStatement.MySqlElseIfStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlParameter;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlWhileStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExtractExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlIntervalExpr;
@@ -1367,4 +1377,130 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS
}
/**
* support procedure
*/
@Override
public boolean visit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
String name = x.getName().toString();
this.variants.put(name, x);
accept(x.getBlock());
return false;
}
@Override
public void endVisit(MySqlCreateProcedureStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlParameter x) {
// TODO Auto-generated method stub
return true;
}
@Override
public void endVisit(MySqlParameter x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlWhileStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlIfStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlElseIfStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlElseStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlElseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlCaseStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlDeclareStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlSelectIntoStatement x) {
// TODO Auto-generated method stub
}
@Override
public boolean visit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
return false;
}
@Override
public void endVisit(MySqlWhenfStatement x) {
// TODO Auto-generated method stub
}
}
@@ -134,6 +134,11 @@ public class Keywords {
map.put("WITH", Token.WITH);
map.put("GRANT", Token.GRANT);
map.put("REVOKE", Token.REVOKE);
// MySql procedure by:zz
map.put("WHILE", Token.WHILE);
map.put("DO", Token.DO);
map.put("DECLARE", Token.DECLARE);
DEFAULT_KEYWORDS = new Keywords(map);
}
@@ -128,6 +128,10 @@ public enum Token {
SHOW("SHOW"),
REPLACE("REPLACE"),
// MySql procedure by:zz
WHILE("WHILE"),
DO("DO"),
//postgresql
WINDOW("WINDOW"),
OFFSET("OFFSET"),
@@ -0,0 +1,86 @@
/*
* Copyright 1999-2101 Alibaba Group Holding Ltd.
*
* 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.bvt.sql.mysql;
import java.util.List;
import org.junit.Assert;
import com.alibaba.druid.sql.MysqlTest;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.stat.TableStat.Column;
public class MySqlCreateProcedureTest extends MysqlTest {
public void test_0() throws Exception {
String sql="create or replace procedure sp_name(level int,age int)"+
" begin"+
" declare x,y,z int;"+
" select id into x,y,z from test;"+
" insert into test values(id,age);"+
" while x do"+
" insert into test values(id,age);"+
" end while"+
" if x then"+
" insert into test values(id,age);"+
" insert into test values(id,age);"+
" else if y then"+
" insert into test values(id,age);"+
" while x do"+
" insert into test values(id,age);"+
" end while"+
" else"+
" insert into test values(id,age);"+
" end if"+
" case x"+
" when x>10 then"+
" insert into test values(id,age);"+
" insert into test values(id,age);"+
" when x>20 then"+
" insert into test values(id,age);"+
" insert into test values(id,age);"+
" else"+
" insert into test values(id,age);"+
" end case"+
" end";
MySqlStatementParser parser=new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement statemen = statementList.get(0);
print(statementList);
Assert.assertEquals(1, statementList.size());
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
statemen.accept(visitor);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("coditions : " + visitor.getConditions());
System.out.println("orderBy : " + visitor.getOrderByColumns());
Assert.assertEquals(1, visitor.getTables().size());
Assert.assertEquals(2, visitor.getColumns().size());
Assert.assertEquals(0, visitor.getConditions().size());
Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("test")));
Assert.assertTrue(visitor.getColumns().contains(new Column("test", "id")));
Assert.assertTrue(visitor.getColumns().contains(new Column("test", "age")));
}
}