diff --git a/pom.xml b/pom.xml index d3f8e4f12b..c6cad14668 100644 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,7 @@ + true public UTF-8 UTF-8 diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCheck.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCheck.java new file mode 100644 index 0000000000..72af8193eb --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCheck.java @@ -0,0 +1,45 @@ +/* + * 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.ast.SQLExpr; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLCheck extends SQLConstaintImpl implements SQLTableElement { + + private static final long serialVersionUID = 1L; + + private SQLExpr expr; + + public SQLExpr getExpr() { + return expr; + } + + public void setExpr(SQLExpr expr) { + this.expr = expr; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, this.getName()); + acceptChild(visitor, this.getExpr()); + } + visitor.endVisit(this); + } + + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.java index 3947ce73da..55fafc03f4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlAlterTableChangeColumn.java @@ -40,7 +40,7 @@ public class MySqlAlterTableChangeColumn extends MySqlObjectImpl implements SQLA if (visitor.visit(this)) { acceptChild(visitor, columnName); acceptChild(visitor, newColumnDefinition); - + acceptChild(visitor, firstColumn); acceptChild(visitor, afterColumn); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java index 796afe85b5..8a065445fb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlCreateTableParser.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.dialect.mysql.parser; import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.statement.SQLCheck; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLSelect; @@ -135,6 +136,13 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { accept(Token.RPAREN); stmt.getTableElementList().add(fk); + } else if (lexer.token() == Token.CHECK) { + lexer.nextToken(); + SQLCheck check = new SQLCheck(); + accept(Token.LPAREN); + check.setExpr(this.exprParser.expr()); + accept(Token.RPAREN); + stmt.getTableElementList().add(check); } if (!(lexer.token() == (Token.COMMA))) { 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 cfa1958973..6745d627ab 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 @@ -307,6 +307,10 @@ public class MySqlStatementParser extends SQLStatementParser { if (identifierEquals(USER)) { return parseCreateUser(); } + + if (lexer.token() == Token.VIEW) { + return parseCreateView(); + } throw new ParserException("TODO " + lexer.token()); } 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 6b67ac6807..f1295d383f 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,8 @@ 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.SQLAlterTableItem; +import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; @@ -1146,6 +1148,11 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS @Override public boolean visit(MySqlAlterTableChangeColumn x) { + SQLAlterTableStatement stmt = (SQLAlterTableStatement) x.getParent(); + String table = stmt.getName().toString(); + + String columnName = x.getColumnName().toString(); + addColumn(table, columnName); return false; } 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 f3d2fe5f9a..7e03f8a6b1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -509,6 +509,8 @@ public class SQLStatementParser extends SQLParser { } else if (identifierEquals("PUBLIC") || identifierEquals("SHARE")) { lexer.reset(markBp, markChar, Token.CREATE); return parseCreateDbLink(); + } else if (token == Token.VIEW) { + return parseCreateView(); } throw new ParserException("TODO " + lexer.token()); @@ -639,7 +641,9 @@ public class SQLStatementParser extends SQLParser { public SQLCreateViewStatement parseCreateView() { SQLCreateViewStatement createView = new SQLCreateViewStatement(); - this.accept(Token.CREATE); + if (lexer.token() == Token.CREATE) { + lexer.nextToken(); + } this.accept(Token.VIEW); 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 86b5d909fa..642fd987f1 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -73,6 +73,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; +import com.alibaba.druid.sql.ast.statement.SQLCheck; import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; @@ -1361,4 +1362,17 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { x.getColumn().accept(this); return false; } + + @Override + public boolean visit(SQLCheck x) { + if (x.getName() != null) { + print("CONSTRAINT "); + x.getName().accept(this); + print(' '); + } + print("CHECK ("); + x.getExpr().accept(this); + 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 6ce1e05b40..5264ceeac9 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -61,6 +61,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; +import com.alibaba.druid.sql.ast.statement.SQLCheck; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLColumnUniqueIndex; @@ -424,4 +425,8 @@ public interface SQLASTVisitor { void endVisit(SQLAlterTableAlterColumn x); boolean visit(SQLAlterTableAlterColumn x); + + boolean visit(SQLCheck x); + + void endVisit(SQLCheck 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 202ff4d4d1..4f417e6e86 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -61,6 +61,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCharactorDataType; +import com.alibaba.druid.sql.ast.statement.SQLCheck; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLColumnPrimaryKey; import com.alibaba.druid.sql.ast.statement.SQLColumnUniqueIndex; @@ -776,4 +777,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { public boolean visit(SQLAlterTableAlterColumn x) { return true; } + + @Override + public boolean visit(SQLCheck x) { + return true; + } + + @Override + public void endVisit(SQLCheck x) { + + } } 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 eee071d965..57bca5f812 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -44,6 +44,7 @@ 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.SQLCreateTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; @@ -1016,4 +1017,9 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { public boolean visit(SQLRollbackStatement x) { return false; } + + public boolean visit(SQLCreateViewStatement x) { + x.getSubQuery().accept(this); + return false; + } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest5.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest5.java index cfecc1c696..c1cd845126 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest5.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest5.java @@ -28,7 +28,7 @@ import com.alibaba.druid.stat.TableStat.Column; public class MySqlAlterTableTest5 extends TestCase { public void test_alter_first() throws Exception { - String sql = "ALTER TABLE table_name change COLUMN column_name char(50)"; + String sql = "ALTER TABLE table_name change COLUMN column_name column_newname char(50)"; MySqlStatementParser parser = new MySqlStatementParser(sql); SQLStatement stmt = parser.parseStatementList().get(0); parser.match(Token.EOF); @@ -43,7 +43,7 @@ public class MySqlAlterTableTest5 extends TestCase { String output = SQLUtils.toMySqlString(stmt); Assert.assertEquals("ALTER TABLE table_name" + // - "\n\tCHANGE COLUMN column_name char(50)", output); + "\n\tCHANGE COLUMN column_name column_newname char(50)", output); Assert.assertEquals(1, visitor.getTables().size()); Assert.assertEquals(1, visitor.getColumns().size()); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest8.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest8.java new file mode 100644 index 0000000000..b60984ab3b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest8.java @@ -0,0 +1,70 @@ +/* + * 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.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlCreateTableTest8 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE TABLE Persons\n" + // + "(\n" + // + "Id_P int NOT NULL,\n" + // + "LastName varchar(255) NOT NULL,\n" + // + "FirstName varchar(255),\n" + // + "Address varchar(255),\n" + // + "City varchar(255),\n" + // + "CHECK (Id_P>0)\n" + // + ")"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + 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(5, visitor.getColumns().size()); + Assert.assertEquals(1, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("Persons"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("Persons", "Id_P"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Persons", "LastName"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Persons", "FirstName"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Persons", "Address"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Persons", "City"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java new file mode 100644 index 0000000000..94de69496e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest9.java @@ -0,0 +1,64 @@ +/* + * 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.mysql; + +import java.util.List; + +import junit.framework.Assert; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; + +public class MySqlCreateTableTest9 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE VIEW view AS\n" + // + "SELECT ProductID,ProductName\n" + // + "FROM Products\n" + // + "WHERE Discontinued=No"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + MySqlCreateTableStatement stmt = (MySqlCreateTableStatement) statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + 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(4, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("Products"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "ProductID"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "ProductName"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "Discontinued"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "No"))); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest.java new file mode 100644 index 0000000000..31f00e9005 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerCreateTableTest.java @@ -0,0 +1,63 @@ +/* + * 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.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLCreateViewStatement; +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 extends TestCase { + + public void test_0() throws Exception { + String sql = "CREATE VIEW [Current Product List] AS\n" + // + "SELECT ProductID,ProductName\n" + // + "FROM Products\n" + // + "WHERE Discontinued=No"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLCreateViewStatement stmt = (SQLCreateViewStatement) 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(4, visitor.getColumns().size()); + Assert.assertEquals(2, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("Products"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "ProductID"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "ProductName"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "Discontinued"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("Products", "No"))); + } +}