From 1150f45f396a99839fc877c958a74fb05e0d7ded Mon Sep 17 00:00:00 2001 From: zhujunxxxxx <455910092@qq.com> Date: Mon, 21 Sep 2015 21:24:22 +0800 Subject: [PATCH] fixed issue#949 --- .../ast/stmt/SQLServerExecStatement.java | 47 +++++++++++++++--- .../parser/SQLServerStatementParser.java | 48 +++++++++++++++++-- .../visitor/SQLServerASTVisitor.java | 5 ++ .../visitor/SQLServerASTVisitorAdapter.java | 13 +++++ .../visitor/SQLServerOutputVisitor.java | 18 +++++++ .../visitor/SQLServerSchemaStatVisitor.java | 13 +++++ .../bvt/sql/sqlserver/SQLServerExec_Test.java | 24 ++++++++++ 7 files changed, 158 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java index 43faa2d97d..1395ca92b4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java @@ -1,8 +1,3 @@ -package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt; - -import java.util.ArrayList; -import java.util.List; - /* * Copyright 1999-2101 Alibaba Group Holding Ltd. * @@ -18,6 +13,11 @@ import java.util.List; * See the License for the specific language governing permissions and * limitations under the License. */ +package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt; + +import java.util.ArrayList; +import java.util.List; + import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; @@ -28,7 +28,7 @@ public class SQLServerExecStatement extends SQLServerObjectImpl implements SQLSe private SQLName returnStatus; private SQLName moduleName; - private List parameters = new ArrayList(); + private List parameters = new ArrayList(); private String dbType; public SQLName getModuleName() { @@ -39,7 +39,7 @@ public class SQLServerExecStatement extends SQLServerObjectImpl implements SQLSe this.moduleName = moduleName; } - public List getParameters() { + public List getParameters() { return parameters; } @@ -67,4 +67,37 @@ public class SQLServerExecStatement extends SQLServerObjectImpl implements SQLSe public void setDbType(String dbType) { this.dbType = dbType; } + + /** + * + * @Description: SQLServer execute Parameter statement + * @author zz email:455910092@qq.com + * @date 2015-9-20 + * @version V1.0 + */ + public static class SQLServerParameter extends SQLServerObjectImpl + { + private SQLExpr expr; + private boolean type;//sql server 支持参数只有input 和 output 两种 + public SQLExpr getExpr() { + return expr; + } + public void setExpr(SQLExpr expr) { + this.expr = expr; + } + public boolean getType() { + return type; + } + public void setType(boolean type) { + this.type = type; + } + @Override + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, expr); + } + visitor.endVisit(this); + + } + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index f49257a66d..42e2281879 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -15,9 +15,12 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.parser; +import java.util.Collection; import java.util.List; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.SQLObject; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; @@ -43,6 +46,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionIsolationLevelStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerWaitForStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLSelectParser; @@ -76,7 +80,7 @@ public class SQLServerStatementParser extends SQLStatementParser { SQLServerExecStatement execStmt = new SQLServerExecStatement(); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); - this.exprParser.exprList(execStmt.getParameters(), execStmt); + this.parseExecParameter(execStmt.getParameters(), execStmt); accept(Token.RPAREN); } else { SQLName sqlNameName = this.exprParser.name(); @@ -88,8 +92,8 @@ public class SQLServerStatementParser extends SQLStatementParser { } else { execStmt.setModuleName(sqlNameName); } - - this.exprParser.exprList(execStmt.getParameters(), execStmt); + + this.parseExecParameter(execStmt.getParameters(), execStmt); } statementList.add(execStmt); return true; @@ -122,6 +126,44 @@ public class SQLServerStatementParser extends SQLStatementParser { return false; } + /** + * SQLServer parse Parameter statement support out type + * @author zz email:455910092@qq.com + * @date 2015-9-20 + */ + public void parseExecParameter(Collection exprCol, SQLObject parent) + { + if (lexer.token() == Token.RPAREN || lexer.token() == Token.RBRACKET) { + return; + } + + if (lexer.token() == Token.EOF) { + return; + } + SQLServerParameter param=new SQLServerParameter(); + SQLExpr expr=this.exprParser.expr(); + expr.setParent(parent); + param.setExpr(expr); + if(lexer.token()==Token.OUT) + { + param.setType(true); + accept(Token.OUT); + } + exprCol.add(param); + while (lexer.token() == Token.COMMA) { + lexer.nextToken(); + param=new SQLServerParameter(); + expr=this.exprParser.expr(); + expr.setParent(parent); + param.setExpr(expr); + if(lexer.token()==Token.OUT) + { + param.setType(true); + accept(Token.OUT); + } + exprCol.add(param); + } + } public SQLStatement parseDeclare() { this.accept(Token.DECLARE); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java index a4f2493898..829d1ca73e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java @@ -26,6 +26,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerBlockStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement.Else; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -117,5 +118,9 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { boolean visit(SQLServerWaitForStatement x); void endVisit(SQLServerWaitForStatement x); + + boolean visit(SQLServerParameter x); + + void endVisit(SQLServerParameter x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java index ba4d4a6e5c..cabb471ae3 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -26,6 +26,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerBlockStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement.Else; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -238,4 +239,16 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(SQLServerParameter x) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void endVisit(SQLServerParameter x) { + // TODO Auto-generated method stub + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index d7c748a0a2..c2c94ac19c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -35,6 +35,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerBlockStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement.Else; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -690,4 +691,21 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe public void endVisit(SQLServerWaitForStatement x) { } + + @Override + public boolean visit(SQLServerParameter x) { + // TODO Auto-generated method stub + x.getExpr().accept(this); + if(x.getType()) + { + print(" OUT"); + } + return false; + } + + @Override + public void endVisit(SQLServerParameter x) { + // TODO Auto-generated method stub + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index cf44d95f8e..c01db613b0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -33,6 +33,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerBlockStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerCommitStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerDeclareStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement.SQLServerParameter; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerIfStatement.Else; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -274,4 +275,16 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL } + @Override + public boolean visit(SQLServerParameter x) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void endVisit(SQLServerParameter x) { + // TODO Auto-generated method stub + + } + } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java index 6c61e6c004..eb6f716c0a 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java @@ -71,4 +71,28 @@ public class SQLServerExec_Test extends TestCase { Assert.assertEquals(0, visitor.getColumns().size()); } + /** + * add by zz to test execute sp with out type + * @throws Exception + */ + public void test_3() throws Exception { + String sql = "EXEC sp_rename @P0 OUT"; + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + + SQLServerSchemaStatVisitor visitor = new SQLServerSchemaStatVisitor(); + stmt.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()); + + String output = SQLUtils.toSQLString(stmt, JdbcConstants.SQL_SERVER); + Assert.assertEquals("EXEC sp_rename @P0 OUT", output); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + } }