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 afc12a2f82..620b0c5a5c 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 @@ -18,7 +18,6 @@ package com.alibaba.druid.sql.dialect.mysql.parser; import java.util.ArrayList; import java.util.List; -import javax.swing.text.AbstractDocument.LeafElement; import com.alibaba.druid.sql.ast.SQLCommentHint; import com.alibaba.druid.sql.ast.SQLDataTypeImpl; @@ -180,6 +179,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTriggersStatem import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowVariantsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnlockTablesStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; @@ -3668,6 +3668,59 @@ public class MySqlStatementParser extends SQLStatementParser { return stmt; } + /** + * zhujun [455910092@qq.com] + * parse spstatement + * @return + */ + public SQLStatement parseSpStatement() { + + // update + if (lexer.token() == (Token.UPDATE)) { + return parseUpdateStatement(); + } + + // create + if (lexer.token() == (Token.CREATE)) { + return parseCreate(); + } + + // insert + if (lexer.token() == Token.INSERT) { + return parseInsert(); + } + + // delete + if (lexer.token() == (Token.DELETE)) { + return parseDeleteStatement(); + } + + // begin + if (lexer.token() == Token.BEGIN) { + return this.parseBlock(); + } + + // 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); + return this.parseSelect(); + } else { + throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); + } + } + // assign statement + if (lexer.token() == Token.SET) { + return parseAssign(); + } + + throw new ParserException("error sp_statement"); + } + /** * 定义异常处理程序 * @author zhujun [455910092@qq.com] @@ -3681,7 +3734,6 @@ public class MySqlStatementParser extends SQLStatementParser { MySqlDeclareHandlerStatement stmt = new MySqlDeclareHandlerStatement(); accept(Token.DECLARE); - //String handlerType = exprParser.name().getSimpleName(); if(lexer.token() == Token.CONTINUE) { stmt.setHandleType(MySqlHandlerType.CONTINUE); @@ -3710,8 +3762,10 @@ public class MySqlStatementParser extends SQLStatementParser { } else if(tokenName.equalsIgnoreCase("SQLSTATE")) { //for SQLSTATE (SQLSTATE '10001') condition.setType(ConditionType.SQLSTATE); - condition.setValue(lexer.stringVal()); - lexer.nextToken(); + lexer.nextToken(); + //condition.setValue(lexer.stringVal()); + //lexer.nextToken(); + condition.setValue(exprParser.name().toString()); } else if(lexer.token() == Token.SQLEXCEPTION) { //for SQLEXCEPTION condition.setType(ConditionType.SYSTEM); condition.setValue(lexer.stringVal()); @@ -3742,20 +3796,13 @@ public class MySqlStatementParser extends SQLStatementParser { } } - stmt.setSpStatement(parseBlock()); + stmt.setSpStatement(parseSpStatement()); - accept(Token.SEMI); + if (!(stmt.getSpStatement() instanceof SQLBlockStatement)) { + accept(Token.SEMI); + } + return stmt; } - /** - * 定义异常 - * @author zhujun [455910092@qq.com] - * 2016-04-16 - * @return - */ - public MySqlDeclareHandlerStatement parseDeclareCondition() { - //TODO - return null; - } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest8.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest8.java index f19040cc45..0348155630 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest8.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateProcedureTest8.java @@ -46,7 +46,7 @@ public class MySqlCreateProcedureTest8 extends MysqlTest { +" declare pass varchar(20);" +" declare done int;" +" declare cur_test CURSOR for select user_name,user_pass from test;" -// +" declare continue handler FOR SQLSTATE '02000' SET done = 1;" + +" declare continue handler FOR SQLSTATE '02000' SET done = 1;" +" if param then" +" select concat_ws(',',user_name,user_pass) into result from test.users where id=param;" +" else" @@ -58,11 +58,6 @@ public class MySqlCreateProcedureTest8 extends MysqlTest { +" close cur_test;" +" end if;" +" end;"; - - sql="create or replace procedure sp_name(level int,age int)"+ - " begin"+ - " declare continue handler FOR SQLEXCEPTION,SQLWARNING begin SET done = 1; end;"+ - " end"; MySqlStatementParser parser=new MySqlStatementParser(sql); List statementList = parser.parseStatementList(); @@ -78,6 +73,131 @@ public class MySqlCreateProcedureTest8 extends MysqlTest { System.out.println("coditions : " + visitor.getConditions()); System.out.println("orderBy : " + visitor.getOrderByColumns()); + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(3, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + + public void test_1() throws Exception { + String sql = "create or replace procedure sp_name(level int,age int)"+ + " begin"+ + " declare continue handler FOR SQLSTATE '02000' SET done = 1;"+ + " 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(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + + public void test_2() throws Exception { + String sql = "create or replace procedure sp_name(level int,age int)"+ + " begin"+ + " declare continue handler FOR SQLEXCEPTION,SQLWARNING SET done = 1;"+ + " 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(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + + public void test_3() throws Exception { + String sql = "create or replace procedure sp_name(level int,age int)"+ + " begin"+ + " declare continue handler FOR 1002 SET done = 1;"+ + " 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(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + + public void test_4() throws Exception { + String sql = "create or replace procedure sp_name(level int,age int)"+ + " begin"+ + " declare continue handler FOR SQLWARNING begin set done = 1; end"+ + " 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(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + } + + public void test_5() throws Exception { + String sql = "create or replace procedure sp_name(level int,age int)"+ + " begin"+ + " declare continue handler FOR SQLWARNING begin set done = 1; end;"+ + " 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(0, visitor.getTables().size()); Assert.assertEquals(0, visitor.getColumns().size()); Assert.assertEquals(0, visitor.getConditions().size());