From 4a66c27b3117a9fbfd76fb5d87f1ef4f8e2bf99c Mon Sep 17 00:00:00 2001 From: zhujunxxxxx <455910092@qq.com> Date: Fri, 11 Sep 2015 20:10:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0mysql=E5=AF=B9procedure?= =?UTF-8?q?=E8=AF=AD=E6=B3=95=E7=9A=84=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mysql/ast/clause/MySqlCaseStatement.java | 103 ++++ .../clause/MySqlCreateProcedureStatement.java | 64 +++ .../ast/clause/MySqlDeclareStatement.java | 55 +++ .../mysql/ast/clause/MySqlElseStatement.java | 35 ++ .../mysql/ast/clause/MySqlIfStatement.java | 95 ++++ .../mysql/ast/clause/MySqlParameter.java | 68 +++ .../ast/clause/MySqlSelectIntoStatement.java | 51 ++ .../mysql/ast/clause/MySqlStatementType.java | 60 +++ .../mysql/ast/clause/MySqlWhileStatement.java | 46 ++ .../executor/MySqlProcedureExecutor.java | 75 +++ .../mysql/parser/MySqlSelectIntoParser.java | 402 ++++++++++++++++ .../mysql/parser/MySqlStatementParser.java | 441 +++++++++++++++++- .../mysql/visitor/MySqlASTVisitor.java | 54 +++ .../mysql/visitor/MySqlASTVisitorAdapter.java | 134 ++++++ .../mysql/visitor/MySqlOutputVisitor.java | 293 ++++++++++++ .../mysql/visitor/MySqlSchemaStatVisitor.java | 136 ++++++ .../alibaba/druid/sql/parser/Keywords.java | 5 + .../com/alibaba/druid/sql/parser/Token.java | 4 + .../sql/mysql/MySqlCreateProcedureTest.java | 86 ++++ 19 files changed, 2203 insertions(+), 4 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCaseStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCreateProcedureStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlElseStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlIfStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlParameter.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlSelectIntoStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/executor/MySqlProcedureExecutor.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCaseStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCaseStatement.java new file mode 100644 index 0000000000..41e7106161 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCaseStatement.java @@ -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 whenList=new ArrayList(); + //else statement + private MySqlElseStatement elseItem; + + public SQLExpr getCondition() { + return condition; + } + + public void setCondition(SQLExpr condition) { + this.condition = condition; + } + + public List getWhenList() { + return whenList; + } + + public void setWhenList(List 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 statements = new ArrayList(); + + @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 getStatements() { + return statements; + } + + public void setStatements(List statements) { + this.statements = statements; + } + + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCreateProcedureStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCreateProcedureStatement.java new file mode 100644 index 0000000000..c65126b962 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlCreateProcedureStatement.java @@ -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 parameters = new ArrayList(); + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, name); + acceptChild(visitor, parameters); + acceptChild(visitor, block); + } + visitor.endVisit(this); + } + + public List getParameters() { + return parameters; + } + + public void setParameters(List 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; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareStatement.java new file mode 100644 index 0000000000..3e752f5fe7 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlDeclareStatement.java @@ -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 varList=new ArrayList(); + + + public List getVarList() { + return varList; + } + public void addVar(SQLExpr expr) + { + varList.add(expr); + } + + public void setVarList(List 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); + + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlElseStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlElseStatement.java new file mode 100644 index 0000000000..341483c293 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlElseStatement.java @@ -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 statements = new ArrayList(); + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, statements); + } + visitor.endVisit(this); + } + + public List getStatements() { + return statements; + } + + public void setStatements(List statements) { + this.statements = statements; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlIfStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlIfStatement.java new file mode 100644 index 0000000000..8e79c133a2 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlIfStatement.java @@ -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 statements = new ArrayList(); + private List elseIfList = new ArrayList(); + 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 getStatements() { + return statements; + } + public void setStatements(List statements) { + this.statements = statements; + } + public List getElseIfList() { + return elseIfList; + } + public void setElseIfList(List 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 statements = new ArrayList(); + + @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 getStatements() { + return statements; + } + + public void setStatements(List statements) { + this.statements = statements; + } + + } + + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlParameter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlParameter.java new file mode 100644 index 0000000000..544f1f9938 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlParameter.java @@ -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); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlSelectIntoStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlSelectIntoStatement.java new file mode 100644 index 0000000000..9bc58a7444 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlSelectIntoStatement.java @@ -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 varList=new ArrayList(); + + public SQLSelect getSelect() { + return select; + } + + public void setSelect(SQLSelect select) { + this.select = select; + } + + public List getVarList() { + return varList; + } + + public void setVarList(List 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); + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java new file mode 100644 index 0000000000..eeabac07bd --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlStatementType.java @@ -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; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java new file mode 100644 index 0000000000..338cf19919 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/clause/MySqlWhileStatement.java @@ -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 statements = new ArrayList(); + + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, condition); + acceptChild(visitor, statements); + } + visitor.endVisit(this); + } + + public List getStatements() { + return statements; + } + + public void setStatements(List statements) { + this.statements = statements; + } + public SQLExpr getCondition() { + return condition; + } + + public void setCondition(SQLExpr condition) { + this.condition = condition; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/executor/MySqlProcedureExecutor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/executor/MySqlProcedureExecutor.java new file mode 100644 index 0000000000..5eae64458d --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/executor/MySqlProcedureExecutor.java @@ -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 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; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java new file mode 100644 index 0000000000..02caf172bd --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java @@ -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 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 parseIntoArgs() { + + List args=new ArrayList(); + 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; + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index d088da66e5..bcdadb57a9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -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 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 statementList) + { + parseProcedureStatementList(statementList,-1); + } + + /** + * parse procedure statement block + */ + private void parseProcedureStatementList(List 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(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 0adf9704bb..28346ca040 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -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); } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 08b7a37484..5036505063 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -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 + } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 2b0f1c999b..d070428cd2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -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 + + } + } // diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index 8b39d16713..f6a2ce4c01 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -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 + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java index 10960e4fd1..7234cb247c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -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); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 401a05ab4d..53e1a5ca44 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -128,6 +128,10 @@ public enum Token { SHOW("SHOW"), REPLACE("REPLACE"), + // MySql procedure by:zz + WHILE("WHILE"), + DO("DO"), + //postgresql WINDOW("WINDOW"), OFFSET("OFFSET"), diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest.java new file mode 100644 index 0000000000..67161d9750 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest.java @@ -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 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"))); + } +}