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 ed5147a5d8..0b6ed3783a 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 @@ -609,11 +609,11 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { MySqlKey key = new MySqlKey(); key.setHasConstaint(hasConstaint); - if (identifierEquals("USING")) { - lexer.nextToken(); - key.setIndexType(lexer.stringVal()); - lexer.nextToken(); - } +// if (identifierEquals("USING")) { +// lexer.nextToken(); +// key.setIndexType(lexer.stringVal()); +// lexer.nextToken(); +// } if (lexer.token() == Token.IDENTIFIER) { SQLName indexName = this.exprParser.name(); @@ -621,6 +621,13 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { key.setIndexName(indexName); } } + + //5.5语法 USING BTREE 放在index 名字后 + if (identifierEquals("USING")) { + lexer.nextToken(); + key.setIndexType(lexer.stringVal()); + lexer.nextToken(); + } accept(Token.LPAREN); for (;;) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index bf7327be01..dd4f8fb289 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -388,12 +388,11 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print(" COLLATE "); print(x.getCollate()); } - } - - if (x.getCollate() != null) { + }else if (x.getCollate() != null) { print(" COLLATE "); print(x.getCollate()); } + return false; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 5f27a30796..bc40bb8f34 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -181,13 +181,39 @@ public class SQLParser { return alias; } + protected void printError(Token token){ + String arround; + if (lexer.mark >= 0 && (lexer.text.length() > lexer.mark + 30)) { + if (lexer.mark - 5 > 0) { + arround = lexer.text.substring(lexer.mark - 5, lexer.mark + 30); + } else { + arround = lexer.text.substring(lexer.mark, lexer.mark + 30); + } + + } else if (lexer.mark >= 0) { + if (lexer.mark - 5 > 0) { + arround = lexer.text.substring(lexer.mark - 5); + } else { + arround = lexer.text.substring(lexer.mark); + } + } else { + arround = lexer.text; + } + + // throw new + // ParserException("syntax error, error arround:'"+arround+"',expect " + // + token + ", actual " + lexer.token() + " " + // + lexer.stringVal() + ", pos " + this.lexer.pos()); + throw new ParserException("syntax error, error in :'" + arround + "',expect " + token + ", actual " + + lexer.token() + " " + lexer.stringVal()); + } + public void accept(Token token) { if (lexer.token() == token) { lexer.nextToken(); } else { setErrorEndPos(lexer.pos()); - throw new ParserException("syntax error, expect " + token + ", actual " + lexer.token() + " " - + lexer.stringVal() + ", pos " + this.lexer.pos()); + printError(token); } } 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 f3d0bd70b9..b37fb6b89a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -297,8 +297,10 @@ public class SQLStatementParser extends SQLParser { continue; } - throw new ParserException("syntax error, " + lexer.token() + " " + lexer.stringVal() + ", pos " - + lexer.pos()); + // throw new ParserException("syntax error, " + lexer.token() + " " + // + lexer.stringVal() + ", pos " + // + lexer.pos()); + printError(lexer.token()); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest18.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest18.java new file mode 100644 index 0000000000..0a946d12f6 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlAlterTableTest18.java @@ -0,0 +1,55 @@ +/* + * 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 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.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.parser.Token; + +public class MySqlAlterTableTest18 extends TestCase { + + public void test_alter_charset() throws Exception { + String sql = "ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) CHARACTER SET gbk NULL FIRST ;"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE `test`.`tb1`\n\tADD COLUMN `f2` VARCHAR(45) CHARACTER SET gbk NULL FIRST", output); + } + + public void test_alter_collate() throws Exception { + String sql = "ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) COLLATE utf8_bin NULL FIRST ;"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE `test`.`tb1`\n\tADD COLUMN `f2` VARCHAR(45) COLLATE utf8_bin NULL FIRST", output); + } + + public void test_alter_charset_collate() throws Exception { + String sql = "ALTER TABLE `test`.`tb1` ADD COLUMN `f2` VARCHAR(45) CHARACTER SET utf8 COLLATE utf8_bin NULL FIRST ;"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + parser.match(Token.EOF); + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("ALTER TABLE `test`.`tb1`\n\tADD COLUMN `f2` VARCHAR(45) CHARACTER SET utf8 COLLATE utf8_bin NULL FIRST", output); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest53.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest53.java new file mode 100644 index 0000000000..898239d2e5 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlCreateTableTest53.java @@ -0,0 +1,157 @@ +/* + * 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 org.junit.Assert; +import org.junit.Test; + +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.stat.TableStat; + +public class MySqlCreateTableTest53 extends MysqlTest { + + @Test + public void test_primary_key_using_btree() throws Exception { + String sql = "CREATE TABLE `ins_ebay_auth` ("// + + "`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',"// + + "`usr_id` int(10) NOT NULL COMMENT '外键,用户表',"// + + "`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',"// + + "`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',"// + + "`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',"// + + "`create_time` datetime NOT NULL COMMENT '授权时间',"// + + "`invalid_time` datetime NOT NULL COMMENT '授权失效时间'," + "PRIMARY KEY USING BTREE (`auth_id`)"// + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + 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(7, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("ins_ebay_auth"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE `ins_ebay_auth` ("// + +"\n\t`auth_id` int(10) AUTO_INCREMENT NOT NULL COMMENT '主键id', " // + +"\n\t`usr_id` int(10) NOT NULL COMMENT '外键,用户表', "// + +"\n\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效', "// + +"\n\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码', "// + +"\n\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名', "// + +"\n\t`create_time` datetime NOT NULL COMMENT '授权时间', "// + +"\n\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间', "// + +"\n\tPRIMARY KEY USING BTREE (`auth_id`)" + +"\n) ENGINE = InnoDB CHARSET = utf8 COLLATE utf8_bin COMMENT = 'INS_EBAY_AUTH'", output); + } + + @Test + public void test_index_using_btree() throws Exception { + String sql = "CREATE TABLE `ins_ebay_auth` ("// + + "`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',"// + + "`usr_id` int(10) NOT NULL COMMENT '外键,用户表',"// + + "`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',"// + + "`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',"// + + "`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',"// + + "`create_time` datetime NOT NULL COMMENT '授权时间',"// + + "`invalid_time` datetime NOT NULL COMMENT '授权失效时间'," + "PRIMARY KEY USING BTREE (`auth_id`), INDEX `ind_usr_id` USING BTREE (`usr_id`)"// + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + 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(7, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("ins_ebay_auth"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE `ins_ebay_auth` ("// + +"\n\t`auth_id` int(10) AUTO_INCREMENT NOT NULL COMMENT '主键id', " // + +"\n\t`usr_id` int(10) NOT NULL COMMENT '外键,用户表', "// + +"\n\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效', "// + +"\n\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码', "// + +"\n\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名', "// + +"\n\t`create_time` datetime NOT NULL COMMENT '授权时间', "// + +"\n\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间', "// + +"\n\tPRIMARY KEY USING BTREE (`auth_id`), " + +"\n\tINDEX `ind_usr_id` USING BTREE (`usr_id`)" + +"\n) ENGINE = InnoDB CHARSET = utf8 COLLATE utf8_bin COMMENT = 'INS_EBAY_AUTH'", output); + } + + @Test + public void test_key_using_btree() throws Exception { + String sql = "CREATE TABLE `ins_ebay_auth` ("// + + "`auth_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',"// + + "`usr_id` int(10) NOT NULL COMMENT '外键,用户表',"// + + "`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效',"// + + "`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码',"// + + "`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名',"// + + "`create_time` datetime NOT NULL COMMENT '授权时间',"// + + "`invalid_time` datetime NOT NULL COMMENT '授权失效时间'," + "PRIMARY KEY USING BTREE (`auth_id`), KEY `ind_usr_id` USING BTREE (`usr_id`)"// + + ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='INS_EBAY_AUTH';"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + SQLStatement stmt = parser.parseCreateTable(); + + 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(7, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("ins_ebay_auth"))); + + String output = SQLUtils.toMySqlString(stmt); + Assert.assertEquals("CREATE TABLE `ins_ebay_auth` ("// + +"\n\t`auth_id` int(10) AUTO_INCREMENT NOT NULL COMMENT '主键id', " // + +"\n\t`usr_id` int(10) NOT NULL COMMENT '外键,用户表', "// + +"\n\t`status` char(1) COLLATE utf8_bin NOT NULL COMMENT '状态 0.有效?1.无效', "// + +"\n\t`ebay_token` varchar(255) COLLATE utf8_bin NOT NULL COMMENT 'eBay授权码', "// + +"\n\t`ebay_name` varchar(50) NOT NULL COMMENT 'eBay唯一名', "// + +"\n\t`create_time` datetime NOT NULL COMMENT '授权时间', "// + +"\n\t`invalid_time` datetime NOT NULL COMMENT '授权失效时间', "// + +"\n\tPRIMARY KEY USING BTREE (`auth_id`), " + +"\n\tKEY `ind_usr_id` USING BTREE (`usr_id`)" + +"\n) ENGINE = InnoDB CHARSET = utf8 COLLATE utf8_bin COMMENT = 'INS_EBAY_AUTH'", output); + } +}