From b9fedcb6d479a0a4d047dda3a66015026d4881ff Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 2 Aug 2013 16:16:35 +0800 Subject: [PATCH] improve sql parser, support sql server --- .../druid/filter/config/ConfigFilter.java | 22 ++-- .../com/alibaba/druid/sql/PagerUtils.java | 5 +- .../java/com/alibaba/druid/sql/SQLUtils.java | 12 +- .../SQLAlterTableDropColumnItem.java | 19 +-- .../ast/statement/SQLColumnDefinition.java | 12 +- .../statement/SQLCreateIndexStatement.java | 16 ++- .../sql/ast/statement/SQLPrimaryKeyImpl.java | 31 +++++ .../druid/sql/ast/statement/SQLUnique.java | 4 + .../mysql/parser/MySqlStatementParser.java | 46 +++++-- .../mysql/visitor/MySqlSchemaStatVisitor.java | 3 +- .../dialect/oracle/parser/OracleLexer.java | 1 - .../oracle/parser/OracleStatementParser.java | 15 +-- .../oracle/visitor/OracleOutputVisitor.java | 23 +--- .../visitor/OracleSchemaStatVisitor.java | 13 +- .../ast/SQLServerColumnDefinition.java | 103 ++++++++++++++++ .../ast/stmt/SQLServerExecStatement.java | 52 ++++++++ .../sqlserver/parser/SQLServerExprParser.java | 36 ++++++ .../sqlserver/parser/SQLServerLexer.java | 1 + .../parser/SQLServerStatementParser.java | 24 +++- .../visitor/SQLServerASTVisitor.java | 15 +++ .../visitor/SQLServerASTVisitorAdapter.java | 40 +++++- .../visitor/SQLServerOutputVisitor.java | 112 +++++++++++++++-- .../visitor/SQLServerSchemaStatVisitor.java | 44 ++++++- .../alibaba/druid/sql/parser/Keywords.java | 1 + .../druid/sql/parser/SQLExprParser.java | 22 +++- .../druid/sql/parser/SQLParserUtils.java | 12 +- .../druid/sql/parser/SQLStatementParser.java | 94 ++++++++++++++- .../sql/visitor/SQLASTOutputVisitor.java | 113 ++++++++++++----- .../druid/sql/visitor/SQLASTVisitor.java | 13 +- .../sql/visitor/SQLASTVisitorAdapter.java | 22 ++++ .../sql/visitor/SQLEvalVisitorUtils.java | 8 +- .../druid/sql/visitor/SchemaStatVisitor.java | 114 ++++++++++++------ .../com/alibaba/druid/stat/TableStat.java | 5 +- .../druid/wall/spi/WallVisitorUtils.java | 3 +- .../wall/SQLServerWallPermitFunctionTest.java | 10 +- .../bvt/filter/wall/SQLServerWallTest_9.java | 52 ++++++++ .../sqlserver/SQLServerAlterTableTest_1.java | 53 ++++++++ .../sqlserver/SQLServerAlterTableTest_2.java | 53 ++++++++ .../sqlserver/SQLServerAlterTableTest_3.java | 53 ++++++++ .../sqlserver/SQLServerAlterTableTest_4.java | 53 ++++++++ .../sqlserver/SQLServerAlterTableTest_5.java | 53 ++++++++ .../sqlserver/SQLServerCreateIndexTest.java | 58 +++++++++ .../sqlserver/SQLServerCreateTableTest_1.java | 72 +++++++++++ .../sqlserver/SQLServerDropIndex_Test.java | 52 ++++++++ .../bvt/sql/sqlserver/SQLServerExec_Test.java | 52 ++++++++ 45 files changed, 1397 insertions(+), 220 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKeyImpl.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerColumnDefinition.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallTest_9.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_2.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_3.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_4.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_5.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateIndexTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerDropIndex_Test.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java diff --git a/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java b/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java index 6f54d09769..4517a240bc 100644 --- a/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java +++ b/src/main/java/com/alibaba/druid/filter/config/ConfigFilter.java @@ -233,22 +233,14 @@ public class ConfigFilter extends FilterAdapter { InputStream inStream = null; try { boolean xml = false; - if (filePath.startsWith("http://") || filePath.startsWith("https://") || filePath.startsWith("file://")) { + if(filePath.startsWith("file://")) { + filePath = filePath.substring("file://".length()); + inStream = getFileAsStream(filePath); + xml = filePath.endsWith(".xml"); + } else if (filePath.startsWith("http://") || filePath.startsWith("https://")) { URL url = new URL(filePath); - try { - inStream = url.openStream(); - xml = url.getPath().endsWith(".xml"); - } catch (UnknownHostException e) { - // 处理本地的文件,格式:file://C:\Users\UserName\AppData\Local\Temp\MyTest6192238555052741793919301884303 - if(url.getHost().length() == 1 && filePath.startsWith("file://")) { - filePath = filePath.substring("file://".length()); - inStream = getFileAsStream(filePath); - xml = filePath.endsWith(".xml"); - } else { - throw new UnknownHostException(e.getMessage()); - } - } - + inStream = url.openStream(); + xml = url.getPath().endsWith(".xml"); } else if (filePath.startsWith("classpath:")) { String resourcePath = filePath.substring("classpath:".length()); inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath); diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index d9b8eb8867..227f7aec87 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -44,6 +44,7 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.util.JdbcUtils; public class PagerUtils { @@ -93,7 +94,7 @@ public class PagerUtils { return limitDB2(select, dbType, offset, count); } - if (JdbcConstants.SQL_SERVER.equals(dbType)) { + if (JdbcConstants.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return limitSQLServer(select, dbType, offset, count); } @@ -354,7 +355,7 @@ public class PagerUtils { return new PGSelectQueryBlock(); } - if (JdbcConstants.SQL_SERVER.equals(dbType)) { + if (JdbcConstants.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerSelectQueryBlock(); } diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index a327234a88..5a872def1a 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -208,11 +208,7 @@ public class SQLUtils { return new PGOutputVisitor(out); } - if (JdbcUtils.SQL_SERVER.equals(dbType)) { - return new SQLServerOutputVisitor(out); - } - - if (JdbcUtils.JTDS.equals(dbType)) { + if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerOutputVisitor(out); } @@ -242,14 +238,10 @@ public class SQLUtils { return new PGSchemaStatVisitor(); } - if (JdbcUtils.SQL_SERVER.equals(dbType)) { + if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerSchemaStatVisitor(); } - if (JdbcUtils.JTDS.equals(dbType)) { - return new SQLServerSchemaStatVisitor(); - } - if (JdbcUtils.DB2.equals(dbType)) { return new DB2SchemaStatVisitor(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropColumnItem.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropColumnItem.java index f210566cdc..22ad99112a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropColumnItem.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLAlterTableDropColumnItem.java @@ -15,6 +15,9 @@ */ package com.alibaba.druid.sql.ast.statement; +import java.util.ArrayList; +import java.util.List; + import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -22,22 +25,22 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLAlterTableDropColumnItem extends SQLObjectImpl implements SQLAlterTableItem { private static final long serialVersionUID = 1L; - private SQLName columnName; + private List columns = new ArrayList(); + + public SQLAlterTableDropColumnItem(){ + + } @Override protected void accept0(SQLASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, columnName); + acceptChild(visitor, columns); } visitor.endVisit(this); } - public SQLName getColumnName() { - return columnName; - } - - public void setColumnName(SQLName columnName) { - this.columnName = columnName; + public List getColumns() { + return columns; } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java index 2b7f542538..e508238337 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLColumnDefinition.java @@ -27,13 +27,13 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; @SuppressWarnings("serial") public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement { - private SQLName name; - private SQLDataType dataType; - private SQLExpr defaultExpr; - private final List constaints = new ArrayList(0); - private String comment; + protected SQLName name; + protected SQLDataType dataType; + protected SQLExpr defaultExpr; + protected final List constaints = new ArrayList(0); + protected String comment; - private Boolean enable; + protected Boolean enable; public SQLColumnDefinition(){ diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java index c5969c5ada..4499ded86a 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateIndexStatement.java @@ -20,6 +20,7 @@ import java.util.List; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLStatement { @@ -36,10 +37,14 @@ public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLS private String type; + public SQLCreateIndexStatement(){ + + } + public SQLTableSource getTable() { return table; } - + public void setTable(SQLName table) { this.setTable(new SQLExprTableSource(table)); } @@ -72,4 +77,13 @@ public class SQLCreateIndexStatement extends SQLStatementImpl implements SQLDDLS this.type = type; } + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, getName()); + acceptChild(visitor, getTable()); + acceptChild(visitor, getItems()); + } + visitor.endVisit(this); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKeyImpl.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKeyImpl.java new file mode 100644 index 0000000000..5784a6e08c --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLPrimaryKeyImpl.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2011 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.ast.statement; + +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +@SuppressWarnings("serial") +public class SQLPrimaryKeyImpl extends SQLUnique implements SQLPrimaryKey { + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.getName()); + acceptChild(visitor, this.getColumns()); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java index d9253df609..305742af84 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUnique.java @@ -26,6 +26,10 @@ public class SQLUnique extends SQLConstaintImpl implements SQLUniqueConstraint, private final List columns = new ArrayList(); + public SQLUnique(){ + + } + public List getColumns() { return columns; } 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 87e245aec3..43481bd829 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 @@ -336,7 +336,7 @@ public class MySqlStatementParser extends SQLStatementParser { if (replace) { lexer.reset(markBp, markChar, Token.CREATE); } - return parseCreateIndex(); + return parseCreateIndex(false); } if (identifierEquals(USER)) { @@ -357,7 +357,11 @@ public class MySqlStatementParser extends SQLStatementParser { throw new ParserException("TODO " + lexer.token()); } - public SQLStatement parseCreateIndex() { + public SQLStatement parseCreateIndex(boolean acceptCreate) { + if (acceptCreate) { + accept(Token.CREATE); + } + MySqlCreateIndexStatement stmt = new MySqlCreateIndexStatement(); if (lexer.token() == Token.UNIQUE) { @@ -385,6 +389,7 @@ public class MySqlStatementParser extends SQLStatementParser { for (;;) { SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem(); + item.setParent(stmt); stmt.getItems().add(item); if (lexer.token() == Token.COMMA) { lexer.nextToken(); @@ -2183,7 +2188,7 @@ public class MySqlStatementParser extends SQLStatementParser { } else if (identifierEquals("ADD")) { lexer.nextToken(); - if (identifierEquals("COLUMN")) { + if (lexer.token() == Token.COLUMN) { lexer.nextToken(); MySqlAlterTableAddColumn item = new MySqlAlterTableAddColumn(); SQLColumnDefinition columnDef = this.exprParser.parseColumn(); @@ -2252,7 +2257,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.getItems().add(item); } else if (lexer.token() == Token.PRIMARY) { - SQLPrimaryKey primaryKey = ((MySqlExprParser) this.exprParser).parsePrimaryKey(); + SQLPrimaryKey primaryKey = this.exprParser.parsePrimaryKey(); SQLAlterTableAddPrimaryKey item = new SQLAlterTableAddPrimaryKey(); item.setPrimaryKey(primaryKey); stmt.getItems().add(item); @@ -2295,7 +2300,7 @@ public class MySqlStatementParser extends SQLStatementParser { } } else if (lexer.token() == Token.ALTER) { lexer.nextToken(); - if (identifierEquals("COLUMN")) { + if (lexer.token() == Token.COLUMN) { lexer.nextToken(); } @@ -2306,7 +2311,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.getItems().add(alterColumn); } else if (identifierEquals("CHANGE")) { lexer.nextToken(); - if (identifierEquals("COLUMN")) { + if (lexer.token() == Token.COLUMN) { lexer.nextToken(); } MySqlAlterTableChangeColumn item = new MySqlAlterTableChangeColumn(); @@ -2326,7 +2331,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.getItems().add(item); } else if (identifierEquals("MODIFY")) { lexer.nextToken(); - if (identifierEquals("COLUMN")) { + if (lexer.token() == Token.COLUMN) { lexer.nextToken(); } MySqlAlterTableModifyColumn item = new MySqlAlterTableModifyColumn(); @@ -2496,14 +2501,35 @@ public class MySqlStatementParser extends SQLStatementParser { SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint(); item.setConstraintName(this.exprParser.name()); stmt.getItems().add(item); - } else if (identifierEquals("COLUMN")) { + } else if (lexer.token() == Token.COLUMN) { lexer.nextToken(); SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); - item.setColumnName(this.exprParser.name()); + + SQLName name = exprParser.name(); + name.setParent(item); + item.getColumns().add(name); + + while (lexer.token() == Token.COMMA) { + lexer.mark(); + lexer.nextToken(); + if (identifierEquals("CHANGE")) { + lexer.reset(); + break; + } + + if (lexer.token() == Token.IDENTIFIER) { + name = exprParser.name(); + name.setParent(item); + } else { + lexer.reset(); + break; + } + } + stmt.getItems().add(item); } else if (lexer.token() == Token.IDENTIFIER) { SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); - item.setColumnName(this.exprParser.name()); + this.exprParser.names(item.getColumns()); stmt.getItems().add(item); } else { super.parseAlterDrop(stmt); 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 385f09b63f..4613d950c7 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 @@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; @@ -1045,7 +1046,7 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlCreateIndexStatement x) { - return false; + return visit((SQLCreateIndexStatement) x); } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 830272c9a8..667f261495 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -37,7 +37,6 @@ public class OracleLexer extends Lexer { map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); map.put("BEGIN", Token.BEGIN); - map.put("COLUMN", Token.COLUMN); map.put("COMMENT", Token.COMMENT); map.put("COMMIT", Token.COMMIT); map.put("CONNECT", Token.CONNECT); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 6ea5685486..0fa18044fc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -849,20 +849,11 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.LPAREN) { lexer.nextToken(); - SQLAlterTableAddColumn item = new SQLAlterTableAddColumn(); - - for (;;) { - SQLColumnDefinition columnDef = this.exprParser.parseColumn(); - item.getColumns().add(columnDef); - if (lexer.token() == Token.COMMA) { - lexer.nextToken(); - continue; - } - break; - } - accept(Token.RPAREN); + SQLAlterTableAddColumn item = parseAlterTableAddColumn(); stmt.getItems().add(item); + + accept(Token.RPAREN); } else if (lexer.token() == Token.CONSTRAINT) { stmt.getItems().add(parseConstaint()); } else { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index c665fe0e2e..4b081ef519 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -36,7 +36,6 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; -import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeTimestamp; @@ -566,13 +565,13 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } public boolean visit(OracleSelectQueryBlock x) { - print("SELECT "); + print("SELECT "); - if (x.getHints().size() > 0) { - printAndAccept(x.getHints(), ", "); + if (x.getHints().size() > 0) { + printAndAccept(x.getHints(), ", "); print(' '); } - + if (SQLSetQuantifier.ALL == x.getDistionOption()) { print("ALL "); } else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) { @@ -919,7 +918,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS } - @Override public void endVisit(OracleTimestampExpr x) { @@ -2332,19 +2330,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS public void endVisit(OraclePrimaryKey x) { } - - @Override - public boolean visit(SQLUnique x) { - if (x.getName() != null) { - print("CONSTRAINT "); - x.getName().accept(this); - print(" "); - } - print("UNIQUE ("); - printAndAccept(x.getColumns(), ", "); - print(")"); - return false; - } @Override public boolean visit(OracleCreateTableStatement x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index 8278187b43..802f3ac6d5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; @@ -1356,17 +1357,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle @Override public boolean visit(OracleCreateIndexStatement x) { - this.setCurrentTable(x); - if (x.getTable() != null) { - String tableName = x.getTable().toString(); - - TableStat stat = this.getTableStat(tableName); - stat.incrementCreateIndexCount(); - this.setCurrentTable(tableName); - - accept(x.getItems()); - } - return false; + return visit((SQLCreateIndexStatement) x); } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerColumnDefinition.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerColumnDefinition.java new file mode 100644 index 0000000000..f9aa063128 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/SQLServerColumnDefinition.java @@ -0,0 +1,103 @@ +/* + * Copyright 1999-2011 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.sqlserver.ast; + +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLServerColumnDefinition extends SQLColumnDefinition implements SQLServerObject { + + private static final long serialVersionUID = 1L; + + private Identity identity; + + public SQLServerColumnDefinition(){ + + } + + public Identity getIdentity() { + return identity; + } + + public void setIdentity(Identity identity) { + if (identity != null) { + identity.setParent(this); + } + this.identity = identity; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + this.accept0((SQLServerASTVisitor) visitor); + } + + @Override + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + this.acceptChild(visitor, name); + this.acceptChild(visitor, dataType); + this.acceptChild(visitor, defaultExpr); + this.acceptChild(visitor, constaints); + this.acceptChild(visitor, identity); + } + visitor.endVisit(this); + } + + @SuppressWarnings("serial") + public static class Identity extends SQLServerObjectImpl { + + private Integer seed; + private Integer increment; + + private boolean notForReplication; + + public Identity() { + + } + + public Integer getSeed() { + return seed; + } + + public void setSeed(Integer seed) { + this.seed = seed; + } + + public Integer getIncrement() { + return increment; + } + + public void setIncrement(Integer increment) { + this.increment = increment; + } + + public boolean isNotForReplication() { + return notForReplication; + } + + public void setNotForReplication(boolean notForReplication) { + this.notForReplication = notForReplication; + } + + @Override + public void accept0(SQLServerASTVisitor visitor) { + visitor.visit(this); + visitor.endVisit(this); + } + + } +} 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 new file mode 100644 index 0000000000..ed1359bd02 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/stmt/SQLServerExecStatement.java @@ -0,0 +1,52 @@ +package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt; + +import java.util.ArrayList; +import java.util.List; + +/* + * Copyright 1999-2011 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. + */ +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; + +@SuppressWarnings("serial") +public class SQLServerExecStatement extends SQLServerObjectImpl implements SQLServerStatement { + + private SQLName moduleName; + private List parameters = new ArrayList(); + + public SQLName getModuleName() { + return moduleName; + } + + public void setModuleName(SQLName moduleName) { + this.moduleName = moduleName; + } + + public List getParameters() { + return parameters; + } + + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.moduleName); + acceptChild(visitor, this.parameters); + } + visitor.endVisit(this); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java index f98b5b0a15..3861838e9d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -17,7 +17,10 @@ package com.alibaba.druid.sql.dialect.sqlserver.parser; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.parser.Lexer; @@ -129,4 +132,37 @@ public class SQLServerExprParser extends SQLExprParser { return null; } + + protected SQLColumnDefinition createColumnDefinition() { + SQLColumnDefinition column = new SQLServerColumnDefinition(); + return column; + } + + public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) { + if (lexer.token() == Token.IDENTITY) { + lexer.nextToken(); + accept(Token.LPAREN); + + SQLIntegerExpr seed = (SQLIntegerExpr) this.primary(); + accept(Token.COMMA); + SQLIntegerExpr increment = (SQLIntegerExpr) this.primary(); + accept(Token.RPAREN); + + SQLServerColumnDefinition.Identity identity = new SQLServerColumnDefinition.Identity(); + identity.setSeed((Integer) seed.getNumber()); + identity.setIncrement((Integer) increment.getNumber()); + + if (lexer.token() == Token.NOT) { + lexer.nextToken(); + accept(Token.FOR); + identifierEquals("REPLICATION "); + identity.setNotForReplication(true); + } + + SQLServerColumnDefinition sqlSreverColumn = (SQLServerColumnDefinition) column; + sqlSreverColumn.setIdentity(identity); + } + + return super.parseColumnRest(column); + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java index d1b5e5f9a0..aab7796ba8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerLexer.java @@ -40,6 +40,7 @@ public class SQLServerLexer extends Lexer { map.put("USE", Token.USE); map.put("WITH", Token.WITH); map.put("PERCENT", Token.PERCENT); + map.put("IDENTITY", Token.IDENTITY); DEFAULT_SQL_SERVER_KEYWORDS = new Keywords(map); } 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 bec3ebfb4a..5b39ebb058 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 @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.parser; import java.util.List; +import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; @@ -25,6 +26,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; @@ -53,6 +55,24 @@ public class SQLServerStatementParser extends SQLStatementParser { return true; } + if (identifierEquals("EXEC") || identifierEquals("EXECUTE")) { + lexer.nextToken(); + + SQLServerExecStatement execStmt = new SQLServerExecStatement(); + if (lexer.token() == Token.LPAREN) { + lexer.nextToken(); + this.exprParser.exprList(execStmt.getParameters(), execStmt); + accept(Token.RPAREN); + } else { + SQLName moduleName = this.exprParser.name(); + execStmt.setModuleName(moduleName); + + this.exprParser.exprList(execStmt.getParameters(), execStmt); + } + statementList.add(execStmt); + return true; + } + return false; } @@ -125,7 +145,7 @@ public class SQLServerStatementParser extends SQLStatementParser { SQLServerUpdateStatement udpateStatement = createUpdateStatement(); accept(Token.UPDATE); - + SQLServerTop top = this.getExprParser().parseTop(); if (top != null) { udpateStatement.setTop(top); @@ -149,7 +169,7 @@ public class SQLServerStatementParser extends SQLStatementParser { return udpateStatement; } - + public SQLServerExprParser getExprParser() { return (SQLServerExprParser) exprParser; } 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 61670e30d3..e328581ae6 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 @@ -15,9 +15,11 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.visitor; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -43,4 +45,17 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { boolean visit(SQLServerUpdateStatement x); void endVisit(SQLServerUpdateStatement x); + + boolean visit(SQLServerColumnDefinition x); + + void endVisit(SQLServerColumnDefinition x); + + boolean visit(SQLServerColumnDefinition.Identity x); + + void endVisit(SQLServerColumnDefinition.Identity x); + + boolean visit(SQLServerExecStatement x); + + void endVisit(SQLServerExecStatement 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 bc8c99c6c4..6f8a5997b9 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 @@ -15,9 +15,11 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.visitor; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; @@ -43,15 +45,15 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements public void endVisit(SQLServerTop x) { } - + @Override public boolean visit(SQLServerObjectReferenceExpr x) { return true; } - + @Override public void endVisit(SQLServerObjectReferenceExpr x) { - + } @Override @@ -61,7 +63,7 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements @Override public void endVisit(SQLServerInsertStatement x) { - + } @Override @@ -71,6 +73,36 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements @Override public void endVisit(SQLServerUpdateStatement x) { + + } + + @Override + public boolean visit(SQLServerColumnDefinition.Identity x) { + return true; + } + + @Override + public void endVisit(SQLServerColumnDefinition.Identity x) { + + } + + @Override + public boolean visit(SQLServerColumnDefinition x) { + return true; + } + + @Override + public void endVisit(SQLServerColumnDefinition x) { + + } + + @Override + public boolean visit(SQLServerExecStatement x) { + return true; + } + + @Override + public void endVisit(SQLServerExecStatement x) { } 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 99440a142d..aa1c7e31e9 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 @@ -15,11 +15,17 @@ */ package com.alibaba.druid.sql.dialect.sqlserver.visitor; +import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLSetQuantifier; +import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition.Identity; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; @@ -47,7 +53,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } printSelectList(x.getSelectList()); - + if (x.getInto() != null) { println(); print("INTO "); @@ -83,24 +89,24 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe @Override public boolean visit(SQLServerTop x) { print("TOP "); - + boolean paren = false; - + if (x.getParent() instanceof SQLServerUpdateStatement) { paren = true; print("("); } - + x.getExpr().accept(this); - + if (paren) { print(")"); } - + if (x.isPercent()) { print(" PERCENT"); } - + return false; } @@ -172,7 +178,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe @Override public boolean visit(SQLServerUpdateStatement x) { print("UPDATE "); - + if (x.getTop() != null) { x.getTop().setParent(x); x.getTop().accept(this); @@ -189,7 +195,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } x.getItems().get(i).accept(this); } - + if (x.getFrom() != null) { println(); print("FROM "); @@ -209,12 +215,12 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe @Override public void endVisit(SQLServerUpdateStatement x) { - + } - + public boolean visit(SQLExprTableSource x) { x.getExpr().accept(this); - + if (x.getHints() != null && x.getHints().size() > 0) { print(" WITH ("); printAndAccept(x.getHints(), ", "); @@ -228,4 +234,86 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe return false; } + + @Override + public boolean visit(Identity x) { + print("IDENTITY ("); + print(x.getSeed()); + print(", "); + print(x.getIncrement()); + print(")"); + return false; + } + + @Override + public void endVisit(Identity x) { + + } + + @Override + public boolean visit(SQLServerColumnDefinition x) { + x.getName().accept(this); + + if (x.getDataType() != null) { + print(' '); + x.getDataType().accept(this); + } + + if (x.getDefaultExpr() != null) { + visitColumnDefault(x); + } + + for (SQLColumnConstraint item : x.getConstaints()) { + print(' '); + item.accept(this); + } + + if (x.getIdentity() != null) { + print(' '); + x.getIdentity().accept(this); + } + + if (x.getEnable() != null) { + if (x.getEnable().booleanValue()) { + print(" ENABLE"); + } + } + + return false; + } + + @Override + public void endVisit(SQLServerColumnDefinition x) { + + } + + public boolean visit(SQLColumnDefinition x) { + if (x instanceof SQLServerColumnDefinition) { + return visit((SQLServerColumnDefinition) x); + } + return super.visit(x); + } + + @Override + public boolean visit(SQLServerExecStatement x) { + print("EXEC "); + SQLName moduleName = x.getModuleName(); + if (moduleName != null) { + moduleName.accept(this); + print(' '); + } else { + print(" ("); + } + printAndAccept(x.getParameters(), ", "); + + if (moduleName == null) { + print(')'); + } + return false; + } + + @Override + public void endVisit(SQLServerExecStatement x) { + + } } 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 5a58f44ee3..d4e1236280 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 @@ -17,25 +17,28 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import java.util.Map; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition.Identity; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.util.JdbcUtils; - public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQLServerASTVisitor { @Override public String getDbType() { return JdbcUtils.SQL_SERVER; } - + @Override public boolean visit(SQLServerSelectQueryBlock x) { return visit((SQLSelectQueryBlock) x); @@ -53,7 +56,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL @Override public void endVisit(SQLServerTop x) { - + } @Override @@ -63,7 +66,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL @Override public void endVisit(SQLServerObjectReferenceExpr x) { - + } @Override @@ -74,7 +77,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL @Override public void endVisit(SQLServerInsertStatement x) { - this.endVisit((SQLInsertStatement) x); + this.endVisit((SQLInsertStatement) x); } @Override @@ -99,8 +102,37 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL @Override public void endVisit(SQLServerUpdateStatement x) { - + } + @Override + public boolean visit(Identity x) { + return false; + } + + @Override + public void endVisit(Identity x) { + + } + + @Override + public boolean visit(SQLServerColumnDefinition x) { + return visit((SQLColumnDefinition) x); + } + + @Override + public void endVisit(SQLServerColumnDefinition x) { + + } + + @Override + public boolean visit(SQLServerExecStatement x) { + return false; + } + + @Override + public void endVisit(SQLServerExecStatement x) { + + } } 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 9c70988c64..f35111b823 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -47,6 +47,7 @@ public class Keywords { map.put("CREATE", Token.CREATE); map.put("DATABASE", Token.DATABASE); map.put("DEFAULT", Token.DEFAULT); + map.put("COLUMN", Token.COLUMN); map.put("DELETE", Token.DELETE); map.put("DESC", Token.DESC); diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index acf3c70ed1..2c8b78049c 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -66,6 +66,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnCheck; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; +import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLUnique; @@ -882,9 +883,9 @@ public class SQLExprParser extends SQLParser { SQLExpr itemExpr = primary(); inListExpr.getTargetList().add(itemExpr); } - + expr = inListExpr; - + if (inListExpr.getTargetList().size() == 1) { SQLExpr targetExpr = inListExpr.getTargetList().get(0); if (targetExpr instanceof SQLQueryExpr) { @@ -1250,13 +1251,18 @@ public class SQLExprParser extends SQLParser { } public SQLColumnDefinition parseColumn() { - SQLColumnDefinition column = new SQLColumnDefinition(); + SQLColumnDefinition column = createColumnDefinition(); column.setName(name()); column.setDataType(parseDataType()); return parseColumnRest(column); } + protected SQLColumnDefinition createColumnDefinition() { + SQLColumnDefinition column = new SQLColumnDefinition(); + return column; + } + public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) { if (lexer.token() == Token.DEFAULT) { lexer.nextToken(); @@ -1302,7 +1308,15 @@ public class SQLExprParser extends SQLParser { } public SQLPrimaryKey parsePrimaryKey() { - throw new ParserException("TODO"); + accept(Token.PRIMARY); + accept(Token.KEY); + + SQLPrimaryKeyImpl pk = new SQLPrimaryKeyImpl(); + accept(Token.LPAREN); + exprList(pk.getColumns()); + accept(Token.RPAREN); + + return pk; } public SQLUnique parseUnique() { diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java index f7c90a83f6..b130b9056e 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParserUtils.java @@ -46,11 +46,7 @@ public class SQLParserUtils { return new PGSQLStatementParser(sql); } - if (JdbcUtils.SQL_SERVER.equals(dbType)) { - return new SQLServerStatementParser(sql); - } - - if (JdbcUtils.JTDS.equals(dbType)) { + if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerStatementParser(sql); } @@ -80,11 +76,7 @@ public class SQLParserUtils { return new PGExprParser(sql); } - if (JdbcUtils.SQL_SERVER.equals(dbType)) { - return new SQLServerExprParser(sql); - } - - if (JdbcUtils.JTDS.equals(dbType)) { + if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerExprParser(sql); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index b067a9296a..5a6e2528d9 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -23,16 +23,22 @@ import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLListExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddPrimaryKey; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableAlterColumn; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDisableKeys; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropColumnItem; import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableConstraint; import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableKeys; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -42,10 +48,12 @@ import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertInto; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; +import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; @@ -228,7 +236,7 @@ public class SQLStatementParser extends SQLParser { lexer.nextToken(); continue; } - + if (lexer.token() == Token.COMMENT) { statementList.add(this.parseComment()); continue; @@ -305,7 +313,17 @@ public class SQLStatementParser extends SQLParser { } else if (identifierEquals("ADD")) { lexer.nextToken(); - throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + if (lexer.token() == Token.PRIMARY) { + SQLPrimaryKey primaryKey = this.exprParser.parsePrimaryKey(); + SQLAlterTableAddPrimaryKey item = new SQLAlterTableAddPrimaryKey(); + item.setPrimaryKey(primaryKey); + stmt.getItems().add(item); + } else if (lexer.token() == Token.IDENTIFIER) { + SQLAlterTableAddColumn item = parseAlterTableAddColumn(); + stmt.getItems().add(item); + } else { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } } else if (identifierEquals("DISABLE")) { lexer.nextToken(); @@ -331,6 +349,17 @@ public class SQLStatementParser extends SQLParser { SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys(); stmt.getItems().add(item); } + } else if (lexer.token() == Token.ALTER) { + lexer.nextToken(); + if (lexer.token() == Token.COLUMN) { + lexer.nextToken(); + SQLColumnDefinition column = this.exprParser.parseColumn(); + SQLAlterTableAlterColumn alterColumn = new SQLAlterTableAlterColumn(); + alterColumn.setColumn(column); + stmt.getItems().add(alterColumn); + } else { + throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); + } } else { break; } @@ -349,6 +378,11 @@ public class SQLStatementParser extends SQLParser { SQLAlterTableDropConstraint item = new SQLAlterTableDropConstraint(); item.setConstraintName(this.exprParser.name()); stmt.getItems().add(item); + } else if (lexer.token() == Token.COLUMN) { + lexer.nextToken(); + SQLAlterTableDropColumnItem item = new SQLAlterTableDropColumnItem(); + this.exprParser.names(item.getColumns()); + stmt.getItems().add(item); } else { throw new ParserException("TODO " + lexer.token() + " " + lexer.stringVal()); } @@ -489,8 +523,11 @@ public class SQLStatementParser extends SQLParser { accept(Token.INDEX); SQLDropIndexStatement stmt = new SQLDropIndexStatement(); stmt.setIndexName(this.exprParser.name()); - accept(Token.ON); - stmt.setTableName(this.exprParser.name()); + + if (lexer.token() == Token.ON) { + lexer.nextToken(); + stmt.setTableName(this.exprParser.name()); + } return stmt; } @@ -612,7 +649,39 @@ public class SQLStatementParser extends SQLParser { } public SQLStatement parseCreateIndex(boolean acceptCreate) { - throw new ParserException("TODO " + lexer.token()); + if (acceptCreate) { + accept(Token.CREATE); + } + + SQLCreateIndexStatement stmt = new SQLCreateIndexStatement(); + if (lexer.token() == Token.UNIQUE) { + stmt.setType("UNIQUE"); + lexer.nextToken(); + } + + accept(Token.INDEX); + + stmt.setName(this.exprParser.name()); + + accept(Token.ON); + + stmt.setTable(this.exprParser.name()); + + accept(Token.LPAREN); + + for (;;) { + SQLSelectOrderByItem item = this.exprParser.parseSelectOrderByItem(); + item.setParent(stmt); + stmt.getItems().add(item); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + break; + } + accept(Token.RPAREN); + + return stmt; } public SQLCreateTableParser getSQLCreateTableParser() { @@ -763,4 +832,19 @@ public class SQLStatementParser extends SQLParser { return stmt; } + + protected SQLAlterTableAddColumn parseAlterTableAddColumn() { + SQLAlterTableAddColumn item = new SQLAlterTableAddColumn(); + + for (;;) { + SQLColumnDefinition columnDef = this.exprParser.parseColumn(); + item.getColumns().add(columnDef); + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + break; + } + return item; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index ff2c5e471e..867bf49033 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -89,6 +89,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropIndexStatement; @@ -97,6 +98,8 @@ import com.alibaba.druid.sql.ast.statement.SQLDropViewStatement; import com.alibaba.druid.sql.ast.statement.SQLExprHint; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; +import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl; +import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource.JoinType; @@ -132,12 +135,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab public SQLASTOutputVisitor(Appendable appender){ this.appender = appender; } - + public int getParametersSize() { if (parameters == null) { return 0; } - + return this.parameters.size(); } @@ -443,10 +446,10 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab printAndAccept(x.getArguments(), ", "); print(")"); } - + return false; } - + public boolean visit(SQLCharactorDataType x) { visit((SQLDataType) x); return false; @@ -485,7 +488,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } public boolean visit(SQLIntegerExpr x) { - return SQLASTOutputVisitorUtils.visit(this, x); + return SQLASTOutputVisitorUtils.visit(this, x); } public boolean visit(SQLMethodInvokeExpr x) { @@ -510,9 +513,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } printAndAccept(x.getArguments(), ", "); - + visitAggreateRest(x); - + print(")"); if (x.getOver() != null) { @@ -521,9 +524,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab } return false; } - + protected void visitAggreateRest(SQLAggregateExpr aggregateExpr) { - + } public boolean visit(SQLAllColumnExpr x) { @@ -736,7 +739,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print(param.toString()); return; } - + if (param instanceof String) { SQLCharExpr charExpr = new SQLCharExpr((String) param); visit(charExpr); @@ -762,7 +765,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print("'"); return; } - + if (param instanceof NClob) { print("'"); return; @@ -772,7 +775,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print("'"); return; } - + print("'" + param.getClass().getName() + "'"); } @@ -1089,13 +1092,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab x.getCondition().accept(this); decrementIndent(); } - + if (x.getUsing().size() > 0) { print(" USING ("); printAndAccept(x.getUsing(), ", "); print(")"); } - + if (x.getAlias() != null) { print(" AS "); print(x.getAlias()); @@ -1254,7 +1257,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab @Override public boolean visit(SQLAlterTableDropColumnItem x) { print("DROP COLUMN "); - x.getColumnName().accept(this); + this.printAndAccept(x.getColumns(), ", "); return false; } @@ -1267,8 +1270,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab public boolean visit(SQLDropIndexStatement x) { print("DROP INDEX "); x.getIndexName().accept(this); - print(" ON "); - x.getTableName().accept(this); + + SQLExprTableSource table = x.getTableName(); + if (table != null) { + print(" ON "); + table.accept(this); + } return false; } @@ -1343,7 +1350,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print(" PRIMARY KEY"); return false; } - + @Override public boolean visit(SQLColumnCheck x) { print("CHECK "); @@ -1386,14 +1393,14 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab return false; } - + @Override public boolean visit(SQLAlterTableAlterColumn x) { print("ALTER COLUMN "); x.getColumn().accept(this); return false; } - + @Override public boolean visit(SQLCheck x) { if (x.getName() != null) { @@ -1406,58 +1413,58 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab print(')'); return false; } - + @Override public boolean visit(SQLAlterTableDropForeinKey x) { print("DROP FOREIGN KEY "); x.getIndexName().accept(this); return false; } - + @Override public boolean visit(SQLAlterTableDropPrimaryKey x) { print("DROP PRIMARY KEY"); return false; } - + @Override public boolean visit(SQLAlterTableEnableKeys x) { print("ENABLE KEYS"); return false; } - + @Override public boolean visit(SQLAlterTableDisableKeys x) { print("DISABLE KEYS"); return false; } - + @Override public boolean visit(SQLAlterTableAddForeignKey x) { print("ADD "); x.getForeignKey().accept(this); return false; } - + public boolean visit(SQLAlterTableDisableConstraint x) { print("DISABLE CONSTRAINT "); x.getConstraintName().accept(this); return false; } - + public boolean visit(SQLAlterTableEnableConstraint x) { print("ENABLE CONSTRAINT "); x.getConstraintName().accept(this); return false; } - + @Override public boolean visit(SQLAlterTableDropConstraint x) { print("DROP CONSTRAINT "); x.getConstraintName().accept(this); return false; } - + @Override public boolean visit(SQLAlterTableStatement x) { print("ALTER TABLE "); @@ -1474,10 +1481,56 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab decrementIndent(); return false; } - + @Override public boolean visit(SQLExprHint x) { x.getExpr().accept(this); return false; } + + @Override + public boolean visit(SQLCreateIndexStatement x) { + print("CREATE "); + if (x.getType() != null) { + print(x.getType()); + print(" "); + } + + print("INDEX "); + + x.getName().accept(this); + print(" ON "); + x.getTable().accept(this); + print(" ("); + printAndAccept(x.getItems(), ", "); + print(")"); + + return false; + } + + @Override + public boolean visit(SQLUnique x) { + if (x.getName() != null) { + print("CONSTRAINT "); + x.getName().accept(this); + print(" "); + } + print("UNIQUE ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + return false; + } + + @Override + public boolean visit(SQLPrimaryKeyImpl x) { + if (x.getName() != null) { + print("CONSTRAINT "); + x.getName().accept(this); + print(" "); + } + print("PRIMARY KEY ("); + printAndAccept(x.getColumns(), ", "); + print(")"); + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 57630c7d3b..1a8448c86e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -72,6 +72,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -82,6 +83,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprHint; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl; import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; @@ -450,8 +452,17 @@ public interface SQLASTVisitor { boolean visit(SQLAlterTableDropConstraint x); void endVisit(SQLAlterTableDropConstraint x); - + boolean visit(SQLUnique x); void endVisit(SQLUnique x); + + boolean visit(SQLPrimaryKeyImpl x); + + void endVisit(SQLPrimaryKeyImpl x); + + boolean visit(SQLCreateIndexStatement x); + + void endVisit(SQLCreateIndexStatement x); + } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index bc1e6ad847..3cf29bc15c 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -72,6 +72,7 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateDatabaseStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -83,6 +84,7 @@ import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; +import com.alibaba.druid.sql.ast.statement.SQLPrimaryKeyImpl; import com.alibaba.druid.sql.ast.statement.SQLReleaseSavePointStatement; import com.alibaba.druid.sql.ast.statement.SQLRollbackStatement; import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement; @@ -861,4 +863,24 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public void endVisit(SQLUnique x) { } + + @Override + public boolean visit(SQLCreateIndexStatement x) { + return true; + } + + @Override + public void endVisit(SQLCreateIndexStatement x) { + + } + + @Override + public boolean visit(SQLPrimaryKeyImpl x) { + return true; + } + + @Override + public void endVisit(SQLPrimaryKeyImpl x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 3a151f5e8f..c8b60a86b2 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -165,10 +165,10 @@ public class SQLEvalVisitorUtils { return new PGEvalVisitor(); } - if (JdbcUtils.SQL_SERVER.equals(dbType)) { + if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { return new SQLServerEvalVisitor(); } - + if (JdbcUtils.DB2.equals(dbType)) { return new DB2EvalVisitor(); } @@ -1576,11 +1576,11 @@ public class SQLEvalVisitorUtils { if (a instanceof Short || b instanceof Short) { Short shortA = castToShort(a); Short shortB = castToShort(b); - + if (shortA == null || shortB == null) { return null; } - + return shortA * shortB; } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index cffedd47b8..93fafdfc77 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -48,6 +48,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCommentStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; @@ -150,38 +151,42 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } private String handleName(String ident) { - boolean flag0 = false; - boolean flag1 = false; - boolean flag2 = false; - boolean flag3 = false; - for (int i = 0; i < ident.length(); ++i) { - final char ch = ident.charAt(i); - if (ch == '\"') { - flag0 = true; - } else if (ch == '`') { - flag1 = true; - } else if (ch == ' ') { - flag2 = true; - } else if (ch == '\'') { - flag3 = true; + int len = ident.length(); + if (ident.charAt(0) == '[' && ident.charAt(len - 1) == ']') { + ident = ident.substring(1, len - 1); + } else { + boolean flag0 = false; + boolean flag1 = false; + boolean flag2 = false; + boolean flag3 = false; + for (int i = 0; i < len; ++i) { + final char ch = ident.charAt(i); + if (ch == '\"') { + flag0 = true; + } else if (ch == '`') { + flag1 = true; + } else if (ch == ' ') { + flag2 = true; + } else if (ch == '\'') { + flag3 = true; + } + } + if (flag0) { + ident = ident.replaceAll("\"", ""); + } + + if (flag1) { + ident = ident.replaceAll("`", ""); + } + + if (flag2) { + ident = ident.replaceAll(" ", ""); + } + + if (flag3) { + ident = ident.replaceAll("'", ""); } } - if (flag0) { - ident = ident.replaceAll("\"", ""); - } - - if (flag1) { - ident = ident.replaceAll("`", ""); - } - - if (flag2) { - ident = ident.replaceAll(" ", ""); - } - - if (flag3) { - ident = ident.replaceAll("'", ""); - } - ident = aliasWrap(ident); return ident; @@ -1152,28 +1157,59 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return false; } - + @Override public boolean visit(SQLAlterTableDropConstraint x) { return false; } - + @Override public boolean visit(SQLDropIndexStatement x) { setMode(x, Mode.DropIndex); - SQLName name = (SQLName) x.getTableName().getExpr(); + SQLExprTableSource table = x.getTableName(); + if (table != null) { + SQLName name = (SQLName) table.getExpr(); - String ident = name.toString(); - setCurrentTable(ident); - - TableStat stat = getTableStat(ident); + String ident = name.toString(); + setCurrentTable(ident); + + TableStat stat = getTableStat(ident); + stat.incrementDropIndexCount(); + + Map aliasMap = getAliasMap(); + if (aliasMap != null) { + aliasMap.put(ident, ident); + } + } + return false; + } + + @Override + public boolean visit(SQLCreateIndexStatement x) { + setMode(x, Mode.CreateIndex); + + SQLName name = (SQLName) ((SQLExprTableSource) x.getTable()).getExpr(); + + String table = name.toString(); + setCurrentTable(table); + + TableStat stat = getTableStat(table); stat.incrementDropIndexCount(); Map aliasMap = getAliasMap(); if (aliasMap != null) { - aliasMap.put(ident, ident); + aliasMap.put(table, table); } - + + for (SQLSelectOrderByItem item : x.getItems()) { + SQLExpr expr = item.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr; + String columnName = identExpr.getName(); + addColumn(table, columnName); + } + } + return false; } } diff --git a/src/main/java/com/alibaba/druid/stat/TableStat.java b/src/main/java/com/alibaba/druid/stat/TableStat.java index 0f23d3769f..44fae8a7c3 100644 --- a/src/main/java/com/alibaba/druid/stat/TableStat.java +++ b/src/main/java/com/alibaba/druid/stat/TableStat.java @@ -509,7 +509,10 @@ public class TableStat { Merge(16), // Truncate(32), // Alter(64), // - Drop(128), DropIndex(256); // + Drop(128), // + DropIndex(256), // + CreateIndex(512)// + ; // public final int mark; diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index ecf80dd4c3..e7718da7a0 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -87,6 +87,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils; import com.alibaba.druid.support.logging.Log; @@ -1687,7 +1688,7 @@ public class WallVisitorUtils { allow = config.isMergeAllow(); denyMessage = "merge not allow"; errorCode = ErrorCode.MERGE_NOT_ALLOW; - } else if (x instanceof SQLCallStatement) { + } else if (x instanceof SQLCallStatement || x instanceof SQLServerExecStatement) { allow = config.isCallAllow(); denyMessage = "call not allow"; errorCode = ErrorCode.CALL_NOT_ALLOW; diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallPermitFunctionTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallPermitFunctionTest.java index 0994da2f8c..483a8cd18e 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallPermitFunctionTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallPermitFunctionTest.java @@ -58,20 +58,20 @@ public class SQLServerWallPermitFunctionTest extends TestCase { } public final void test_sp_addsrvrolemenber() throws Exception { - Assert.assertFalse(WallUtils.isValidateSqlServer("EXEC master.dbo.sp_addsrvrolemember ‘user’, ‘sysadmin")); + Assert.assertTrue(WallUtils.isValidateSqlServer("EXEC master.dbo.sp_addsrvrolemember ‘user’, ‘sysadmin")); } public final void test_sp_helpdb() throws Exception { - Assert.assertFalse(WallUtils.isValidateSqlServer("EXEC sp_helpdb master")); - Assert.assertFalse(WallUtils.isValidateSqlServer("EXEC sp_helpdb pubs")); + Assert.assertTrue(WallUtils.isValidateSqlServer("EXEC sp_helpdb master")); + Assert.assertTrue(WallUtils.isValidateSqlServer("EXEC sp_helpdb pubs")); } public final void test_sp_droplogin() throws Exception { - Assert.assertFalse(WallUtils.isValidateSqlServer("EXEC sp_droplogin ‘user’;")); + Assert.assertTrue(WallUtils.isValidateSqlServer("EXEC sp_droplogin ‘user’;")); } public final void test_sp_addlogin() throws Exception { - Assert.assertFalse(WallUtils.isValidateSqlServer("EXEC sp_addlogin ‘user’, ‘pass’; ")); + Assert.assertTrue(WallUtils.isValidateSqlServer("EXEC sp_addlogin ‘user’, ‘pass’; ")); } public final void test_db_name() throws Exception { diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallTest_9.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallTest_9.java new file mode 100644 index 0000000000..cb31deadd5 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/SQLServerWallTest_9.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2011 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.filter.wall; + +import java.util.Collections; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.wall.WallProvider; +import com.alibaba.druid.wall.spi.SQLServerWallProvider; + +/** + * SQLServerWallTest + * + * @author RaymondXiu + * @version 1.0, 2012-3-18 + * @see + */ +public class SQLServerWallTest_9 extends TestCase { + + public void test_true() throws Exception { + WallProvider provider = new SQLServerWallProvider(); + + String sql = "SELECT s.id FROM snapshots s " // + + "WHERE s.scope='PRJ'"// + + " and s.qualifier IN ('TRK', 'BRC')"// + + " AND status='P'" // + + " AND islast=0" // + + " AND NOT EXISTS (select m.id from project_measures m WHERE m.snapshot_id=s.id)"; + + Assert.assertTrue(provider.checkValid(sql)); + + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_1.java new file mode 100644 index 0000000000..fa3862310b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_1.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerAlterTableTest_1 extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "ALTER TABLE dependencies ALTER COLUMN id bigint"; + 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("ALTER TABLE dependencies" // + + "\n\tALTER COLUMN id bigint", output); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_2.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_2.java new file mode 100644 index 0000000000..bc49cb56e0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_2.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerAlterTableTest_2 extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "ALTER TABLE dependencies ADD PRIMARY KEY(id)"; + 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("ALTER TABLE dependencies" // + + "\n\tADD PRIMARY KEY (id)", output); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_3.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_3.java new file mode 100644 index 0000000000..5da34ab97b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_3.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerAlterTableTest_3 extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "ALTER TABLE extensions ADD [core] bit"; + 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("ALTER TABLE extensions" // + + "\n\tADD ([core] bit)", output); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_4.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_4.java new file mode 100644 index 0000000000..8194c0a79b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_4.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerAlterTableTest_4 extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "ALTER TABLE extensions DROP COLUMN [category]"; + 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("ALTER TABLE extensions" // + + "\n\tDROP COLUMN [category]", output); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_5.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_5.java new file mode 100644 index 0000000000..678404af5d --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerAlterTableTest_5.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerAlterTableTest_5 extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "ALTER TABLE project_measures DROP COLUMN diff_value_1, diff_value_2, diff_value_3"; + 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("ALTER TABLE project_measures" // + + "\n\tDROP COLUMN diff_value_1, diff_value_2, diff_value_3", output); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(3, visitor.getColumns().size()); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateIndexTest.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateIndexTest.java new file mode 100644 index 0000000000..40c8a9012f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateIndexTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import java.util.List; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class SQLServerCreateIndexTest extends TestCase { + + public void test_0() throws Exception { + String sql = "CREATE UNIQUE INDEX [unique_schema_migrations] ON [schema_migrations] ([version])"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLCreateIndexStatement stmt = (SQLCreateIndexStatement) statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + 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()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(1, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("schema_migrations"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("schema_migrations", "version"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest_1.java new file mode 100644 index 0000000000..51e432c372 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest_1.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import java.util.List; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class SQLServerCreateTableTest_1 extends TestCase { + + public void test_0() throws Exception { + String sql = "CREATE TABLE [projects] ("// + + "[id] int NOT NULL IDENTITY(1, 1) PRIMARY KEY, "// + + "[name] NVARCHAR(256), [description] NVARCHAR(2000), "// + + "[enabled] bit DEFAULT 1 NOT NULL, "// + + "[scope] NVARCHAR(3), "// + + "[qualifier] NVARCHAR(3), "// + + "[kee] NVARCHAR(400), "// + + "[root_id] int, " // + + "[profile_id] int, " // + + "[language] NVARCHAR(5), "// + + "[copy_resource_id] int, "// + + "[long_name] NVARCHAR(256)) "; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLCreateTableStatement stmt = (SQLCreateTableStatement) statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + 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()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(12, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("projects"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("projects", "id"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("projects", "name"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("projects", "enabled"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("projects", "scope"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerDropIndex_Test.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerDropIndex_Test.java new file mode 100644 index 0000000000..8f476cc36b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerDropIndex_Test.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerDropIndex_Test extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "DROP INDEX async_measure_snapshots.async_m_s_snapshot_id"; + 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("DROP INDEX async_measure_snapshots.async_m_s_snapshot_id", output); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + } + +} 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 new file mode 100644 index 0000000000..9055e3d276 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerExec_Test.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2011 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.sqlserver; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerSchemaStatVisitor; +import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.util.JdbcConstants; + +public class SQLServerExec_Test extends TestCase { + + public void test_alter_first() throws Exception { + String sql = "EXEC sp_rename 'rules.temp_plugin_config_key', 'plugin_config_key'"; + 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 'rules.temp_plugin_config_key', 'plugin_config_key'", output); + + Assert.assertEquals(0, visitor.getTables().size()); + Assert.assertEquals(0, visitor.getColumns().size()); + } + +}