diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2CreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2CreateTableParser.java index 985831aaa1..126a45fd28 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2CreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/parser/DB2CreateTableParser.java @@ -170,6 +170,15 @@ public class DB2CreateTableParser extends SQLCreateTableParser { lexer.nextToken(); SQLName validproc = this.exprParser.name(); createTable.setValidproc(validproc); + continue; + } else if (lexer.identifierEquals(FnvHash.Constants.COMPRESS)) { + lexer.nextToken(); + createTable.setCompress(true); + + if (lexer.identifierEquals(FnvHash.Constants.YES)) { + lexer.nextToken(); + } + continue; } break; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java index d3176c7cc8..ddd07192bb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java @@ -118,6 +118,16 @@ public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisit partitionBy.accept(this); } + Boolean compress = x.getCompress(); + if (compress != null) { + println(); + if (compress.booleanValue()) { + print0(ucase ? "COMPRESS YES" : "compress yes"); + } else { + print0(ucase ? "COMPRESS NO" : "compress no"); + } + } + return false; } 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 a1550de8cb..8f5409003b 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 @@ -116,10 +116,15 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { stmt.setSelect(query); } else { for (;;) { + SQLColumnDefinition column = null; if (lexer.token() == Token.IDENTIFIER // || lexer.token() == Token.LITERAL_CHARS) { - SQLColumnDefinition column = this.exprParser.parseColumn(); + column = this.exprParser.parseColumn(); stmt.getTableElementList().add(column); + + if (lexer.isKeepComments() && lexer.hasComment()) { + column.addAfterComment(lexer.readAndResetComments()); + } } else if (lexer.token() == Token.CONSTRAINT // || lexer.token() == Token.PRIMARY // || lexer.token() == Token.UNIQUE) { @@ -175,14 +180,17 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { SQLCheck check = this.exprParser.parseCheck(); stmt.getTableElementList().add(check); } else { - SQLColumnDefinition column = this.exprParser.parseColumn(); + column = this.exprParser.parseColumn(); stmt.getTableElementList().add(column); } - if (!(lexer.token() == (Token.COMMA))) { + if (lexer.token() != Token.COMMA) { break; } else { lexer.nextToken(); + if (lexer.isKeepComments() && lexer.hasComment() && column != null) { + column.addAfterComment(lexer.readAndResetComments()); + } } } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java index 1fea3c8299..19ad187d02 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsCreateTableParser.java @@ -124,7 +124,7 @@ public class OdpsCreateTableParser extends SQLCreateTableParser { column.addAfterComment(lexer.readAndResetComments()); } - if (!(lexer.token() == (Token.COMMA))) { + if (lexer.token() != Token.COMMA) { break; } else { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index bec1f8e824..959c65647c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -1523,7 +1523,7 @@ public class OracleExprParser extends SQLExprParser { lexer.nextToken(); attributes.setCompress(Boolean.FALSE); continue; - } else if (lexer.identifierEquals("COMPRESS")) { + } else if (lexer.identifierEquals(FnvHash.Constants.COMPRESS)) { lexer.nextToken(); attributes.setCompress(Boolean.TRUE); 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 8cf9e6b704..d717eae675 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -2428,21 +2428,33 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet protected void printTableElements(List tableElementList) { int size = tableElementList.size(); - if (size > 0) { - print0(" ("); - this.indentCount++; - println(); - for (int i = 0; i < size; ++i) { - if (i != 0) { - print0(","); - println(); - } - tableElementList.get(i).accept(this); - } - this.indentCount--; - println(); - print(')'); + if (size == 0) { + return; } + + print0(" ("); + + this.indentCount++; + println(); + for (int i = 0; i < size; ++i) { + SQLTableElement element = tableElementList.get(i); + element.accept(this); + + if (i != size - 1) { + print(','); + } + if (this.isPrettyFormat() && element.hasAfterComment()) { + print(' '); + printlnComment(element.getAfterCommentsDirect()); + } + + if (i != size - 1) { + println(); + } + } + this.indentCount--; + println(); + print(')'); } public boolean visit(SQLCreateTableStatement x) { diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 50dd4a6053..1a187a6ad5 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -513,5 +513,7 @@ public final class FnvHash { long NONE = fnv1a_64_lower("NONE"); long PARTITIONING = fnv1a_64_lower("PARTITIONING"); long VALIDPROC = fnv1a_64_lower("VALIDPROC"); + long COMPRESS = fnv1a_64_lower("COMPRESS"); + long YES = fnv1a_64_lower("YES"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_04.java b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_04.java new file mode 100644 index 0000000000..5041aafb3f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/db2/DB2CreateTableTest_04.java @@ -0,0 +1,90 @@ +/* + * Copyright 1999-2017 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.db2; + +import com.alibaba.druid.sql.DB2Test; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; +import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class DB2CreateTableTest_04 extends DB2Test { + + public void test_0() throws Exception { + String sql = "CREATE TABLE CUSTOMER\n" + + " (CUSTOMERNUM INTEGER,\n" + + " CUSTOMERNAME VARCHAR(80),\n" + + " ADDRESS VARCHAR(200),\n" + + " CITY VARCHAR(50),\n" + + " COUNTRY VARCHAR(50),\n" + + " CODE VARCHAR(15),\n" + + " CUSTOMERNUMDIM INTEGER)\n" + + " COMPRESS YES;"; + + DB2StatementParser parser = new DB2StatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + System.out.println(SQLUtils.toDB2String(stmt)); + + Assert.assertEquals(1, statementList.size()); + + DB2SchemaStatVisitor visitor = new DB2SchemaStatVisitor(); + 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(7, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.containsTable("CUSTOMER")); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("DSN8B10.EMP", "WORKDEPT"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name"))); + // Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "full_name"))); + + Assert.assertEquals("CREATE TABLE CUSTOMER (\n" + + "\tCUSTOMERNUM INTEGER,\n" + + "\tCUSTOMERNAME VARCHAR(80),\n" + + "\tADDRESS VARCHAR(200),\n" + + "\tCITY VARCHAR(50),\n" + + "\tCOUNTRY VARCHAR(50),\n" + + "\tCODE VARCHAR(15),\n" + + "\tCUSTOMERNUMDIM INTEGER\n" + + ")\n" + + "COMPRESS YES;", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2)); + + Assert.assertEquals("create table CUSTOMER (\n" + + "\tCUSTOMERNUM INTEGER,\n" + + "\tCUSTOMERNAME VARCHAR(80),\n" + + "\tADDRESS VARCHAR(200),\n" + + "\tCITY VARCHAR(50),\n" + + "\tCOUNTRY VARCHAR(50),\n" + + "\tCODE VARCHAR(15),\n" + + "\tCUSTOMERNUMDIM INTEGER\n" + + ")\n" + + "compress yes;", // + SQLUtils.toSQLString(stmt, JdbcConstants.DB2, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest82.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest82.java new file mode 100644 index 0000000000..d2d14c1030 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest82.java @@ -0,0 +1,59 @@ +/* + * Copyright 1999-2017 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.createTable; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; + +public class MySqlCreateTableTest82 extends MysqlTest { + + public void test_one() throws Exception { + String sql = "CREATE TABLE t1 (\n" + + " ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + + " dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n" + + ");"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); +// +// Column column = visitor.getColumn("tb_custom_vip_show_message", "custom_vip_show_message_seq"); +// assertNotNull(column); +// assertEquals("INT", column.getDataType()); + System.out.println(stmt); + + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("CREATE TABLE t1 (\n" + + "\tts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n" + + "\tdt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP\n" + + ")", output); + } + + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("create table t1 (\n" + + "\tts TIMESTAMP default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,\n" + + "\tdt DATETIME default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP\n" + + ")", output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest83.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest83.java new file mode 100644 index 0000000000..7879752a5f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest83.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2017 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.createTable; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.parser.SQLParserFeature; + +public class MySqlCreateTableTest83 extends MysqlTest { + + public void test_one() throws Exception { + String sql = "CREATE TABLE t1 (\n" + + " ts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- default 0\n" + + " ts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL\n" + + ");"; + + MySqlStatementParser parser = new MySqlStatementParser(sql, SQLParserFeature.KeepComments); + SQLStatement stmt = parser.parseCreateTable(); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); +// +// Column column = visitor.getColumn("tb_custom_vip_show_message", "custom_vip_show_message_seq"); +// assertNotNull(column); +// assertEquals("INT", column.getDataType()); + System.out.println(stmt); + + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("CREATE TABLE t1 (\n" + + "\tts1 TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- default 0\n" + + "\tts2 TIMESTAMP NULL ON UPDATE CURRENT_TIMESTAMP -- default NULL\n" + + ")", output); + } + + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("create table t1 (\n" + + "\tts1 TIMESTAMP on update CURRENT_TIMESTAMP, -- default 0\n" + + "\tts2 TIMESTAMP null on update CURRENT_TIMESTAMP -- default NULL\n" + + ")", output); + } + } +}