From 3823b1fc375da66a4fa3eea7bd4ceb56a54cda75 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 28 May 2018 09:56:25 +0800 Subject: [PATCH 01/10] change version to 1.1.11 --- pom.xml | 2 +- src/main/java/com/alibaba/druid/VERSION.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 04f6b37989..2104fe36d0 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.alibaba druid - 1.1.9-preview_1 + 1.1.11-preview_1 jar druid diff --git a/src/main/java/com/alibaba/druid/VERSION.java b/src/main/java/com/alibaba/druid/VERSION.java index 00d4063dec..5411c788d8 100644 --- a/src/main/java/com/alibaba/druid/VERSION.java +++ b/src/main/java/com/alibaba/druid/VERSION.java @@ -19,7 +19,7 @@ public final class VERSION { public final static int MajorVersion = 1; public final static int MinorVersion = 1; - public final static int RevisionVersion = 10; + public final static int RevisionVersion = 11; public static String getVersionNumber() { return VERSION.MajorVersion + "." + VERSION.MinorVersion + "." + VERSION.RevisionVersion; From 9c8b14bd4ada53e1df4bfbee1bd1f9b31fbf1fb1 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 28 May 2018 09:57:16 +0800 Subject: [PATCH 02/10] bug fixed for sql parser nchar literal support. for issue #2558 --- .../com/alibaba/druid/sql/parser/Lexer.java | 1 + .../sql/sqlserver/SQLServerUpdateTest6.java | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 443a95316f..4aba23d22a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -474,6 +474,7 @@ public class Lexer { } if (c1 == '\'') { + bufPos = 0; ++pos; ch = '\''; scanString(); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java new file mode 100644 index 0000000000..5e47cf8c6e --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerUpdateTest6.java @@ -0,0 +1,39 @@ +/* + * 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.sqlserver; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import junit.framework.TestCase; + +public class SQLServerUpdateTest6 extends TestCase { + + public void test_update() throws Exception { + String sql = "update clients set name =N'小明',age =1"; + + String expect = "UPDATE TOP (10) HumanResources.Employee" + + "\nSET VacationHours = VacationHours * 1.25, ModifiedDate = GETDATE()" + + "\nOUTPUT inserted.BusinessEntityID, deleted.VacationHours, inserted.VacationHours, inserted.ModifiedDate" + + "\n\tINTO @MyTableVar;"; + + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + assertEquals("UPDATE clients\n" + + "SET name = N'小明', age = 1", stmt.toString()); + } +} From 58d3814c2bb39d4313cf3f026b65842fc103e666 Mon Sep 17 00:00:00 2001 From: Sean Zhang Date: Thu, 31 May 2018 11:03:46 +0800 Subject: [PATCH 03/10] Fix capitalization of some alphabets to make them look more beautiful --- .../resources/support/http/resources/js/lang.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/resources/support/http/resources/js/lang.js b/src/main/resources/support/http/resources/js/lang.js index 5953ad54af..8dedabf525 100644 --- a/src/main/resources/support/http/resources/js/lang.js +++ b/src/main/resources/support/http/resources/js/lang.js @@ -10,7 +10,7 @@ druid.lang = function() { 'WebApp' : ['WebApp' , 'Web应用'], 'WebURI' : ['WebURI' , 'URI监控'], 'Web Session' : ['Web Session' , 'Session监控'], - 'Spring' : ['Spring' , 'spring监控'], + 'Spring' : ['Spring' , 'Spring监控'], 'JSON API' : ['JSON API' , 'JSON API'], 'ResetAll' : ['Reset All' , '重置'], 'LogAndReset' : ['Log And Reset' , '记录日志并重置'], @@ -21,8 +21,8 @@ druid.lang = function() { 'Drivers' : ['Drivers' , '驱动'], 'ResetEnable' : ['ResetEnable' , '是否允许重置'], 'ResetCount' : ['ResetCount' , '重置次数'], - 'JavaVersion' : ['JavaVersion' , 'java版本'], - 'JavaVMName' : ['JavaVMName' , 'jvm名称'], + 'JavaVersion' : ['JavaVersion' , 'Java版本'], + 'JavaVMName' : ['JavaVMName' , 'JVM名称'], 'JavaClassPath' : ['JavaClassPath' , 'classpath路径'], 'StartTime' : ['StartTime' , '启动时间'], @@ -79,9 +79,9 @@ druid.lang = function() { 'SQLList' : ['SQL List', 'sql列表'], 'UserNameDesc' : ['Specify the username used when creating a new connection.', '指定建立连接时使用的用户名'], - 'URLDesc' : ['The JDBC driver connection URL', 'jdbc连接字符串'], + 'URLDesc' : ['The JDBC driver connection URL', 'JDBC连接字符串'], 'DbTypeDesc' : ['database type', '数据库类型'], - 'DriverClassNameDesc' : ['The fully qualifed name of the JDBC driver class', 'jdbc驱动的类名'], + 'DriverClassNameDesc' : ['The fully qualifed name of the JDBC driver class', 'JDBC驱动的类名'], 'FilterClassNamesDesc' : ['All the fully qualifed name of the filter classes', 'filter的类名'], 'TestOnBorrowDesc' : [' Test or not when borrow a connection', '是否在获得连接后检测其可用性'], 'TestWhileIdleDesc' : ['Test or not when a connection is idle for a while', '是否在连接空闲一段时间后检测其可用性'], @@ -232,8 +232,8 @@ druid.lang = function() { 'WallStat':['Wall Stat', '防御统计'], 'TableStat':['Table Stat', '表访问统计'], 'FunctionStat':['Function Stat', '函数调用统计'], - 'SQLStatWhiteList':['SQL Stat - White List', 'SQL防御统计 - 白名单'], - 'SQLStatBlackList':['SQL Stat - Black List', 'SQL防御统计 - 黑名单'], + 'SQLStatWhiteList':['SQL Stat - White List', 'SQL防御统计 - 白名单'], + 'SQLStatBlackList':['SQL Stat - Black List', 'SQL防御统计 - 黑名单'], /**session-detail*/ 'PrincipalOnly':['Principal Only', 'Principal过滤'], 'SESSIONID':['SESSIONID', 'SESSIONID'], From ca38876d1e3cd2b4b382f7588e3ebaa88b2cbc10 Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 31 May 2018 13:51:32 +0800 Subject: [PATCH 04/10] improved sql paser for aliyun analyticdb. --- .../sql/ast/statement/SQLDumpStatement.java | 85 ++++++++++ .../druid/sql/parser/SQLStatementParser.java | 27 ++++ .../sql/visitor/SQLASTOutputVisitor.java | 26 +++ .../druid/sql/visitor/SQLASTVisitor.java | 3 + .../sql/visitor/SQLASTVisitorAdapter.java | 9 +- .../druid/sql/visitor/SchemaStatVisitor.java | 19 +++ .../java/com/alibaba/druid/util/FnvHash.java | 2 + .../druid/bvt/sql/mysql/MySqlDumpTest.java | 64 ++++++++ .../druid/bvt/sql/mysql/MySqlDumpTest_1.java | 59 +++++++ .../sql/mysql/select/MySqlSelectTest_188.java | 151 ++++++++++++++++++ 10 files changed, 444 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java new file mode 100644 index 0000000000..f555699836 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLDumpStatement.java @@ -0,0 +1,85 @@ +/* + * Copyright 1999-2018 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.ast.SQLStatementImpl; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; + +public class SQLDumpStatement extends SQLStatementImpl { + private boolean overwrite; + private SQLExprTableSource into; + + private SQLSelect select; + + public SQLDumpStatement() { + + } + + public SQLSelect getSelect() { + return select; + } + + public void setSelect(SQLSelect x) { + if (x != null) { + x.setParent(this); + } + + this.select = x; + } + + public SQLExprTableSource getInto() { + return into; + } + + public void setInto(SQLExpr x) { + if (x == null) { + return; + } + + setInto(new SQLExprTableSource(x)); + } + + public void setInto(SQLExprTableSource x) { + if (x != null) { + x.setParent(this); + } + + this.into = x; + } + + public boolean isOverwrite() { + return overwrite; + } + + public void setOverwrite(boolean overwrite) { + this.overwrite = overwrite; + } + + @Override + protected void accept0(SQLASTVisitor visitor) { + if (visitor.visit(this)) { + if (into != null) { + into.accept(visitor); + } + + if (select != null) { + select.accept(visitor); + } + } + visitor.endVisit(this); + } +} 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 0174f36a6c..a44c3dd1a4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -370,6 +370,13 @@ public class SQLStatementParser extends SQLParser { continue; } + if (lexer.identifierEquals("DUMP")) { + SQLStatement stmt = parseDump(); + statementList.add(stmt); + + continue; + } + if (lexer.identifierEquals(FnvHash.Constants.COMMIT)) { SQLStatement stmt = parseCommit(); @@ -427,6 +434,26 @@ public class SQLStatementParser extends SQLParser { } } + public SQLStatement parseDump() { + SQLDumpStatement stmt = new SQLDumpStatement(); + acceptIdentifier("DUMP"); + acceptIdentifier("DATA"); + + if (lexer.identifierEquals(FnvHash.Constants.OVERWRITE)) { + lexer.nextToken(); + stmt.setOverwrite(true); + } + + if (lexer.token == Token.INTO) { + lexer.nextToken(); + stmt.setInto(this.exprParser.expr()); + } + + SQLSelect select = createSQLSelectParser().select(); + stmt.setSelect(select); + return stmt; + } + public SQLStatement parseDrop() { List beforeComments = null; 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 4eef77f071..5ec6432940 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -6579,6 +6579,32 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet return false; } + @Override + public boolean visit(SQLDumpStatement x) { + List headHints = x.getHeadHintsDirect(); + if (headHints != null) { + for (SQLCommentHint hint : headHints) { + hint.accept(this); + println(); + } + } + + print0(ucase ? "DUMP DATA " : "dump data "); + + + if (x.isOverwrite()) { + print0(ucase ? "OVERWRITE " : "overwrite "); + } + + SQLExprTableSource into = x.getInto(); + if (into != null) { + into.accept(this); + } + + x.getSelect().accept(this); + return false; + } + public void print(float value) { if (this.appender == null) { return; 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 17285df6bb..3e72e44c92 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -842,4 +842,7 @@ public interface SQLASTVisitor { boolean visit(SQLWindow x); void endVisit(SQLWindow x); + boolean visit(SQLDumpStatement x); + void endVisit(SQLDumpStatement 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 1900a2dfa7..459f863299 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -1990,7 +1990,6 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } - @Override public boolean visit(SQLWindow x) { return true; @@ -2000,6 +1999,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { } + @Override + public boolean visit(SQLDumpStatement x) { + return true; + } + + public void endVisit(SQLDumpStatement x) { + + } public final boolean isEnabled(VisitorFeature feature) { return VisitorFeature.isEnabled(this.features, feature); 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 d7c989ac66..e1de81e413 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -2515,4 +2515,23 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } return false; } + + public boolean visit(SQLDumpStatement x) { + if (repository != null + && x.getParent() == null) { + repository.resolve(x); + } + + final SQLExprTableSource into = x.getInto(); + if (into != null) { + into.accept(this); + } + + final SQLSelect select = x.getSelect(); + if (select != null) { + select.accept(this); + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 0a65b9e82d..5be48ac625 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -649,5 +649,7 @@ public final class FnvHash { long GENERATED = fnv1a_64_lower("GENERATED"); long ALWAYS = fnv1a_64_lower("ALWAYS"); long INCREMENT = fnv1a_64_lower("INCREMENT"); + + long OVERWRITE = fnv1a_64_lower("OVERWRITE"); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java new file mode 100644 index 0000000000..d151892209 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest.java @@ -0,0 +1,64 @@ +/* + * 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; + +import com.alibaba.druid.sql.MysqlTest; +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 java.util.List; + +public class MySqlDumpTest extends MysqlTest { + + public void test_0() throws Exception { + String sql = "dump data into 'odps://ktv_market_analyzing/bohan_test_001/ds=20171233/seller_bucket=9727' " + + "select '6225607' as crowd_snapshot_id, a.seller_id as seller_id, a.buyer_id as buyer_id " + + "from amp.otpx_buyer_seller_relation_detail_to_garuda a " + + "join amp.otp_user_base_info b on b.user_id= a.buyer_id " + + "where(((a.seller_id= 765844183 and a.seller_zone= 765844183%20+ 1000)) and((a.last_pay_date>= 20151226 and a.last_pay_date<= 20171215)) and((a.is_market_target in('3'))))"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); +// print(statementList); + + 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()); + + assertEquals(2, visitor.getTables().size()); + assertEquals(6, visitor.getColumns().size()); + assertEquals(7, visitor.getConditions().size()); + + assertTrue(visitor.containsTable("amp.otp_user_base_info")); + assertTrue(visitor.containsTable("amp.otpx_buyer_seller_relation_detail_to_garuda")); +// assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + + assertTrue(visitor.containsColumn("amp.otp_user_base_info", "user_id")); + assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "buyer_id")); + assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "seller_id")); + assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "seller_zone")); + assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "is_market_target")); + assertTrue(visitor.containsColumn("amp.otpx_buyer_seller_relation_detail_to_garuda", "last_pay_date")); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.java new file mode 100644 index 0000000000..d87546884a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDumpTest_1.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; + +import com.alibaba.druid.sql.MysqlTest; +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 java.util.List; + +public class MySqlDumpTest_1 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "DUMP DATA OVERWRITE INTO 'odps://cod_garuda/wenyu_meta_person' select cid, cname, dept, gender, pid from wenyu_meta_person limit 10;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); +// print(statementList); + + 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()); + + assertEquals(1, visitor.getTables().size()); + assertEquals(5, visitor.getColumns().size()); + assertEquals(0, visitor.getConditions().size()); + + assertTrue(visitor.containsTable("wenyu_meta_person")); +// assertTrue(visitor.getTables().containsKey(new TableStat.Name("t2"))); + + assertTrue(visitor.containsColumn("wenyu_meta_person", "cid")); + assertTrue(visitor.containsColumn("wenyu_meta_person", "cname")); + assertTrue(visitor.containsColumn("wenyu_meta_person", "dept")); + assertTrue(visitor.containsColumn("wenyu_meta_person", "gender")); + assertTrue(visitor.containsColumn("wenyu_meta_person", "pid")); + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java new file mode 100644 index 0000000000..43f465dedb --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_188.java @@ -0,0 +1,151 @@ +package com.alibaba.druid.bvt.sql.mysql.select; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; + +import java.util.List; + +public class MySqlSelectTest_188 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "( ( SELECT user_id FROM (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) WHERE create_time>'2018-01-01 00:00:00' EXCEPT SELECT user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) ) UNION SELECT coalesce(a.user_id, b.user_id) as user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) a LEFT JOIN (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label,account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank,order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) b ON a.user_id = b.user_id WHERE ( (a.create_time>'2018-01-01 00:00:00') or (a.create_time is null and b.create_time>'2018-01-01 00:00:00') ) ) INTERSECT ( SELECT coalesce(a.user_id, b.user_id) as user_id FROM (select user_id, create_time, reg_channel, src, certified_from, certified_time, account_certify_type, is_certified, crm_label, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order from user_info_online where user_id = 1953401122571952) a FULL JOIN (select user_id, havana_id, create_time, reg_days, own, reg_own_group, reg_src_group, reg_channel, src, global_city_name, locale, cid, cid_name, account_certify_type, certified_from, certified_time, certify_type, is_certified, account_type, address, age, sex, birthday, global_province_name, group_phone_area_no, group_phone_zone_no, l_level, crm_label,account_structure, account_frozen, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user, is_net_user, parent_pk, taobao_account, update_time, user_region, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority, crm_customer_rank,order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d,count_1_yq_visit,count_7_yq_visit,count_15_yq_visit,count_30_yq_visit,count_1_promotion_visit,count_7_promotion_visit,count_15_promotion_visit,count_30_promotion_visit,count_1_market_visit,count_7_market_visit,count_15_market_visit,count_30_market_visit,count_1_search_visit,count_7_search_visit,count_15_search_visit,count_30_search_visit,count_1_help_visit,count_7_help_visit,count_15_help_visit,count_30_help_visit,count_7_domain_visit,count_15_domain_visit,count_30_domain_visit,count_1_beian_visit,count_7_beian_visit,count_15_beian_visit,count_30_beian_visit,count_1_wanwang_visit,count_7_wanwang_visit,count_15_wanwang_visit,count_30_wanwang_visit,count_1_domain_visit,crm_biz_category,cloud_pay_greater_zero_order_cnt, retain_cnt_d, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d from user_info_offline where user_id = 1953401122571952) b ON a.user_id = b.user_id WHERE ( (a.account_certify_type='personal') or (a.account_certify_type is null and b.account_certify_type='personal') ) )"; + +// System.out.println(sql); + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLSelectStatement stmt = (SQLSelectStatement)statementList.get(0); + + assertEquals(1, statementList.size()); + + assertEquals("((SELECT user_id\n" + + "FROM (\n" + + "\tSELECT user_id, havana_id, create_time, reg_days, own\n" + + "\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" + + "\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" + + "\t\t, certified_time, certify_type, is_certified, account_type, address\n" + + "\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" + + "\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" + + "\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" + + "\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" + + "\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" + + "\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" + + "\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" + + "\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" + + "\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" + + "\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" + + "\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" + + "\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" + + "\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" + + "\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" + + "\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" + + "\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" + + "\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" + + "\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" + + "\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" + + "\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" + + "\tFROM user_info_offline\n" + + "\tWHERE user_id = 1953401122571952\n" + + ")\n" + + "WHERE create_time > '2018-01-01 00:00:00'\n" + + "EXCEPT\n" + + "SELECT user_id\n" + + "FROM (\n" + + "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" + + "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" + + "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" + + "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" + + "\t\t, count_redis_paid_order, count_communicate_paid_order\n" + + "\tFROM user_info_online\n" + + "\tWHERE user_id = 1953401122571952\n" + + "))\n" + + "UNION\n" + + "SELECT coalesce(a.user_id, b.user_id) AS user_id\n" + + "FROM (\n" + + "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" + + "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" + + "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" + + "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" + + "\t\t, count_redis_paid_order, count_communicate_paid_order\n" + + "\tFROM user_info_online\n" + + "\tWHERE user_id = 1953401122571952\n" + + ") a\n" + + "\tLEFT JOIN (\n" + + "\t\tSELECT user_id, havana_id, create_time, reg_days, own\n" + + "\t\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" + + "\t\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" + + "\t\t\t, certified_time, certify_type, is_certified, account_type, address\n" + + "\t\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" + + "\t\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" + + "\t\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" + + "\t\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" + + "\t\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" + + "\t\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" + + "\t\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" + + "\t\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" + + "\t\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" + + "\t\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" + + "\t\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" + + "\t\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" + + "\t\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" + + "\t\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" + + "\t\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" + + "\t\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" + + "\t\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" + + "\t\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" + + "\t\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" + + "\t\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" + + "\t\tFROM user_info_offline\n" + + "\t\tWHERE user_id = 1953401122571952\n" + + "\t) b\n" + + "\tON a.user_id = b.user_id\n" + + "WHERE a.create_time > '2018-01-01 00:00:00'\n" + + "\tOR (a.create_time IS NULL\n" + + "\t\tAND b.create_time > '2018-01-01 00:00:00'))\n" + + "INTERSECT\n" + + "(SELECT coalesce(a.user_id, b.user_id) AS user_id\n" + + "FROM (\n" + + "\tSELECT user_id, create_time, reg_channel, src, certified_from\n" + + "\t\t, certified_time, account_certify_type, is_certified, crm_label, order_cnt\n" + + "\t\t, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order, count_rds_paid_order, count_oss_paid_order\n" + + "\t\t, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order, count_mongodb_paid_order, count_eip_paid_order\n" + + "\t\t, count_redis_paid_order, count_communicate_paid_order\n" + + "\tFROM user_info_online\n" + + "\tWHERE user_id = 1953401122571952\n" + + ") a\n" + + "\tFULL JOIN (\n" + + "\t\tSELECT user_id, havana_id, create_time, reg_days, own\n" + + "\t\t\t, reg_own_group, reg_src_group, reg_channel, src, global_city_name\n" + + "\t\t\t, locale, cid, cid_name, account_certify_type, certified_from\n" + + "\t\t\t, certified_time, certify_type, is_certified, account_type, address\n" + + "\t\t\t, age, sex, birthday, global_province_name, group_phone_area_no\n" + + "\t\t\t, group_phone_zone_no, l_level, crm_label, account_structure, account_frozen\n" + + "\t\t\t, hid_b2b, hid_taobao, is_aliyun_test_user, is_aliyun_user, is_enterprise\n" + + "\t\t\t, is_enterprise_account, is_global_user, is_net_test_user, is_oversea_user, is_valid_reg_user\n" + + "\t\t\t, is_net_user, parent_pk, taobao_account, update_time, user_region\n" + + "\t\t\t, fenxiao_create_time, fenxiao_label, fenxiao_parent_uid, fenxiao_region, crm_customer_priority\n" + + "\t\t\t, crm_customer_rank, order_cnt, cloud_order_cnt, cloud_market_order_cnt, count_ecs_paid_order\n" + + "\t\t\t, count_rds_paid_order, count_oss_paid_order, count_cdn_paid_order, count_slb_paid_order, count_nas_paid_order\n" + + "\t\t\t, count_mongodb_paid_order, count_eip_paid_order, count_redis_paid_order, count_communicate_paid_order, is_paid_retain\n" + + "\t\t\t, count_1_all_visit, count_7_all_visit, count_15_all_visit, count_30_all_visit, is_retain_d\n" + + "\t\t\t, count_1_yq_visit, count_7_yq_visit, count_15_yq_visit, count_30_yq_visit, count_1_promotion_visit\n" + + "\t\t\t, count_7_promotion_visit, count_15_promotion_visit, count_30_promotion_visit, count_1_market_visit, count_7_market_visit\n" + + "\t\t\t, count_15_market_visit, count_30_market_visit, count_1_search_visit, count_7_search_visit, count_15_search_visit\n" + + "\t\t\t, count_30_search_visit, count_1_help_visit, count_7_help_visit, count_15_help_visit, count_30_help_visit\n" + + "\t\t\t, count_7_domain_visit, count_15_domain_visit, count_30_domain_visit, count_1_beian_visit, count_7_beian_visit\n" + + "\t\t\t, count_15_beian_visit, count_30_beian_visit, count_1_wanwang_visit, count_7_wanwang_visit, count_15_wanwang_visit\n" + + "\t\t\t, count_30_wanwang_visit, count_1_domain_visit, crm_biz_category, cloud_pay_greater_zero_order_cnt, retain_cnt_d\n" + + "\t\t\t, retain_cnt_ecs_d, retain_cnt_rds_d, retain_cnt_oss_d, retain_cnt_cdn_d, retain_cnt_slb_d\n" + + "\t\t\t, retain_cnt_nas_d, retain_cnt_mangodb_d, retain_cnt_eip_d, retain_cnt_redis_d, retain_cnt_communication_d\n" + + "\t\t\t, retain_cnt_domain_d, retain_cnt_email_d, retain_cnt_dns_d\n" + + "\t\tFROM user_info_offline\n" + + "\t\tWHERE user_id = 1953401122571952\n" + + "\t) b\n" + + "\tON a.user_id = b.user_id\n" + + "WHERE a.account_certify_type = 'personal'\n" + + "\tOR (a.account_certify_type IS NULL\n" + + "\t\tAND b.account_certify_type = 'personal'))", stmt.toString()); + } +} \ No newline at end of file From 6c3154e33d5cf50a2504149e63b7051e6d30134b Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 31 May 2018 14:32:25 +0800 Subject: [PATCH 05/10] improved sql paser for mysql. issue #2611 --- .../ast/statement/SQLColumnDefinition.java | 15 ++++++ .../statement/SQLCreateTableStatement.java | 31 ++++++++++++ .../druid/sql/ast/statement/SQLUnique.java | 12 +++++ .../ast/statement/SQLUniqueConstraint.java | 1 + .../mysql/parser/MySqlCreateTableParser.java | 47 ++++++++++++++++- .../sql/dialect/mysql/parser/MySqlLexer.java | 1 + .../mysql/parser/MySqlStatementParser.java | 9 ++-- .../druid/sql/parser/SQLStatementParser.java | 2 +- .../com/alibaba/druid/sql/parser/Token.java | 1 + .../createTable/MySqlCreateTableTest112.java | 50 +++++++++++++++++++ 10 files changed, 161 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java 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 8cd4d02ddb..bb868c9e0a 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 @@ -431,6 +431,21 @@ public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElemen return false; } + public boolean isPrimaryKey() { + for (SQLColumnConstraint constraint : constraints) { + if (constraint instanceof SQLColumnPrimaryKey) { + return true; + } + } + + if (parent instanceof SQLCreateTableStatement) { + return ((SQLCreateTableStatement) parent) + .isPrimaryColumn(nameHashCode64()); + } + + return false; + } + public String toString() { return SQLUtils.toSQLString(this, dbType); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index 5b8fec750b..41dc46db0f 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -1107,4 +1107,35 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS this.rowFormat = x; } + public SQLColumnDefinition getColumn(String name) { + if (name == null) { + return null; + } + + return getColumn( + FnvHash.hashCode64(name) + ); + } + + public SQLColumnDefinition getColumn(long nameHash) { + for (SQLTableElement element : this.tableElementList) { + if (element instanceof SQLColumnDefinition) { + SQLColumnDefinition column = (SQLColumnDefinition) element; + if (column.nameHashCode64() == nameHash) { + return column; + } + } + } + + return null; + } + + public boolean isPrimaryColumn(long columnNameHash) { + SQLPrimaryKey pk = this.findPrimaryKey(); + if (pk == null) { + return false; + } + + return pk.containsColumn(columnNameHash); + } } 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 d34fa6e202..68e2da2b37 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 @@ -73,6 +73,18 @@ public class SQLUnique extends SQLConstraintImpl implements SQLUniqueConstraint, return false; } + public boolean containsColumn(long columnNameHash) { + for (SQLSelectOrderByItem item : columns) { + SQLExpr expr = item.getExpr(); + if (expr instanceof SQLIdentifierExpr) { + if (((SQLIdentifierExpr) expr).nameHashCode64() == columnNameHash) { + return true; + } + } + } + return false; + } + public void cloneTo(SQLUnique x) { super.cloneTo(x); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java index 1d14b9efa9..73906a9460 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLUniqueConstraint.java @@ -24,4 +24,5 @@ public interface SQLUniqueConstraint extends SQLConstraint { List getColumns(); boolean containsColumn(String column); + boolean containsColumn(long columnNameHash); } 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 03dbc80cf8..00d19ac00d 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 @@ -106,7 +106,7 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { stmt.setSelect(query); } else { for (;;) { - if (lexer.identifierEquals(FnvHash.Constants.FULLTEXT)) { + if (lexer.token() == Token.FULLTEXT) { Lexer.SavePoint mark = lexer.mark(); lexer.nextToken(); if (lexer.token() == Token.KEY) { @@ -119,8 +119,51 @@ public class MySqlCreateTableParser extends SQLCreateTableParser { lexer.nextToken(); continue; } + } else if (lexer.token() == Token.INDEX) { + lexer.nextToken(); + MySqlTableIndex idx = new MySqlTableIndex(); + idx.setIndexType("FULLTEXT"); + idx.setName(this.exprParser.name()); + + accept(Token.LPAREN); + for (; ; ) { + idx.addColumn(this.exprParser.parseSelectOrderByItem()); + if (!(lexer.token() == (Token.COMMA))) { + break; + } else { + lexer.nextToken(); + } + } + stmt.getTableElementList().add(idx); + accept(Token.RPAREN); + if (lexer.token() == Token.RPAREN) { + break; + } else if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } } else { - lexer.reset(mark); + MySqlTableIndex idx = new MySqlTableIndex(); + idx.setIndexType("FULLTEXT"); + idx.setName(this.exprParser.name()); + + accept(Token.LPAREN); + for (; ; ) { + idx.addColumn(this.exprParser.parseSelectOrderByItem()); + if (!(lexer.token() == (Token.COMMA))) { + break; + } else { + lexer.nextToken(); + } + } + stmt.getTableElementList().add(idx); + accept(Token.RPAREN); + if (lexer.token() == Token.RPAREN) { + break; + } else if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } } } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) { Lexer.SavePoint mark = lexer.mark(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 1f61cb122a..c559b25cd2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -64,6 +64,7 @@ public class MySqlLexer extends Lexer { map.put("MOD", Token.MOD); map.put("CONTAINS", Token.CONTAINS); map.put("RLIKE", Token.RLIKE); + map.put("FULLTEXT", Token.FULLTEXT); DEFAULT_MYSQL_KEYWORDS = new Keywords(map); } 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 0b6b0663fb..845b28cbd5 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 @@ -65,7 +65,6 @@ public class MySqlStatementParser extends SQLStatementParser { private static final String TABLES = "TABLES"; private static final String TEMPORARY = "TEMPORARY"; private static final String SPATIAL = "SPATIAL"; - private static final String FULLTEXT = "FULLTEXT"; private static final String LOW_PRIORITY = "LOW_PRIORITY"; private static final String CONNECTION = "CONNECTION"; private static final String EXTENDED = "EXTENDED"; @@ -258,7 +257,7 @@ public class MySqlStatementParser extends SQLStatementParser { return parseCreateDatabase(); } - if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || lexer.identifierEquals(FULLTEXT) + if (lexer.token() == Token.UNIQUE || lexer.token() == Token.INDEX || lexer.token() == Token.FULLTEXT || lexer.identifierEquals(SPATIAL)) { if (replace) { lexer.reset(markBp, markChar, Token.CREATE); @@ -505,8 +504,8 @@ public class MySqlStatementParser extends SQLStatementParser { if (lexer.token() == Token.UNIQUE) { stmt.setType("UNIQUE"); lexer.nextToken(); - } else if (lexer.identifierEquals(FULLTEXT)) { - stmt.setType(FULLTEXT); + } else if (lexer.token() == Token.FULLTEXT) { + stmt.setType("FULLTEXT"); lexer.nextToken(); } else if (lexer.identifierEquals(SPATIAL)) { stmt.setType(SPATIAL); @@ -3463,7 +3462,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); parseAlterTableAddColumn(stmt); } else if (lexer.token() == Token.INDEX - || lexer.identifierEquals(FnvHash.Constants.FULLTEXT) + || lexer.token() == Token.FULLTEXT || lexer.identifierEquals(FnvHash.Constants.SPATIAL)) { SQLAlterTableAddIndex item = parseAlterTableAddIndex(); item.setParent(stmt); 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 a44c3dd1a4..1466043612 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -2804,7 +2804,7 @@ public class SQLStatementParser extends SQLParser { protected SQLAlterTableAddIndex parseAlterTableAddIndex() { SQLAlterTableAddIndex item = new SQLAlterTableAddIndex(); - if (lexer.identifierEquals(FnvHash.Constants.FULLTEXT)) { + if (lexer.token == Token.FULLTEXT) { lexer.nextToken(); item.setType("FULLTEXT"); } else if (lexer.identifierEquals(FnvHash.Constants.SPATIAL)) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index fd9f07cdd8..a3a28bee92 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -102,6 +102,7 @@ public enum Token { IN("IN"), CONTAINS("CONTAINS"), RLIKE("RLIKE"), + FULLTEXT("FULLTEXT"), NEW("NEW"), ASC("ASC"), diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java new file mode 100644 index 0000000000..d439a6d871 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java @@ -0,0 +1,50 @@ +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.ast.statement.SQLColumnDefinition; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlCreateTableTest112 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "CREATE TABLE opening_lines ( " + + "id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY" + + ", opening_line TEXT(500)" + + ", author VARCHAR(200)" + + ", title VARCHAR(200)" + + ", FULLTEXT idx (opening_line) " + + ") ENGINE=InnoDB;"; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + MySqlCreateTableStatement stmt = (MySqlCreateTableStatement)statementList.get(0); + + assertEquals(1, statementList.size()); + assertEquals(5, stmt.getTableElementList().size()); + + assertEquals("CREATE TABLE opening_lines (\n" + + "\tid INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,\n" + + "\topening_line TEXT(500),\n" + + "\tauthor VARCHAR(200),\n" + + "\ttitle VARCHAR(200),\n" + + "\tFULLTEXT INDEX idx(opening_line)\n" + + ") ENGINE = InnoDB;", stmt.toString()); + + SchemaStatVisitor v = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.accept(v); + + assertEquals(4, v.getColumns().size()); + SQLColumnDefinition column = stmt.getColumn("id"); + assertNotNull(column); + assertEquals(2, column.getConstraints().size()); + assertTrue(column.isPrimaryKey()); + } + +} \ No newline at end of file From 3d7a66ff3f830f29b3f5f21253162149648191c9 Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 31 May 2018 15:13:40 +0800 Subject: [PATCH 06/10] removed duplicate method. --- .../statement/SQLCreateTableStatement.java | 23 ------------------- .../createTable/MySqlCreateTableTest112.java | 2 +- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java index 41dc46db0f..aef97407ce 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLCreateTableStatement.java @@ -1107,29 +1107,6 @@ public class SQLCreateTableStatement extends SQLStatementImpl implements SQLDDLS this.rowFormat = x; } - public SQLColumnDefinition getColumn(String name) { - if (name == null) { - return null; - } - - return getColumn( - FnvHash.hashCode64(name) - ); - } - - public SQLColumnDefinition getColumn(long nameHash) { - for (SQLTableElement element : this.tableElementList) { - if (element instanceof SQLColumnDefinition) { - SQLColumnDefinition column = (SQLColumnDefinition) element; - if (column.nameHashCode64() == nameHash) { - return column; - } - } - } - - return null; - } - public boolean isPrimaryColumn(long columnNameHash) { SQLPrimaryKey pk = this.findPrimaryKey(); if (pk == null) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java index d439a6d871..b8141e7b6a 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/createTable/MySqlCreateTableTest112.java @@ -41,7 +41,7 @@ public class MySqlCreateTableTest112 extends MysqlTest { stmt.accept(v); assertEquals(4, v.getColumns().size()); - SQLColumnDefinition column = stmt.getColumn("id"); + SQLColumnDefinition column = stmt.findColumn("id"); assertNotNull(column); assertEquals(2, column.getConstraints().size()); assertTrue(column.isPrimaryKey()); From 00a9b92ca1c28a06fc1117c7b878aa00b90dd476 Mon Sep 17 00:00:00 2001 From: wenshao Date: Thu, 21 Jun 2018 09:54:08 +0800 Subject: [PATCH 07/10] improved mysql parser support. --- .../statement/MySqlLockTableStatement.java | 101 ++++++++++----- .../mysql/parser/MySqlStatementParser.java | 120 +++++++++++++----- .../mysql/visitor/MySqlASTVisitor.java | 4 + .../mysql/visitor/MySqlASTVisitorAdapter.java | 10 ++ .../mysql/visitor/MySqlOutputVisitor.java | 19 ++- .../mysql/visitor/MySqlSchemaStatVisitor.java | 10 ++ .../java/com/alibaba/druid/util/FnvHash.java | 1 + .../druid/bvt/sql/mysql/AdsDumpTest_0.java | 32 +++++ .../sql/mysql/update/MySqlUpdateTest_17.java | 77 +++++++++++ 9 files changed, 309 insertions(+), 65 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java index 0e3ddbe078..724e14ce08 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlLockTableStatement.java @@ -15,47 +15,22 @@ */ package com.alibaba.druid.sql.dialect.mysql.ast.statement; +import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLCommentHint; -import com.alibaba.druid.sql.ast.SQLName; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlObjectImpl; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor; public class MySqlLockTableStatement extends MySqlStatementImpl { - private SQLExprTableSource tableSource; - - private LockType lockType; - - private List hints; - - public SQLExprTableSource getTableSource() { - return tableSource; - } - - public void setTableSource(SQLExprTableSource tableSource) { - if (tableSource != null) { - tableSource.setParent(this); - } - this.tableSource = tableSource; - } - - public void setTableSource(SQLName name) { - setTableSource(new SQLExprTableSource(name)); - } - - public LockType getLockType() { - return lockType; - } - - public void setLockType(LockType lockType) { - this.lockType = lockType; - } + private List items = new ArrayList(); + @Override public void accept0(MySqlASTVisitor visitor) { if (visitor.visit(this)) { - acceptChild(visitor, tableSource); + acceptChild(visitor, items); } visitor.endVisit(this); } @@ -70,11 +45,69 @@ public class MySqlLockTableStatement extends MySqlStatementImpl { } } - public List getHints() { - return hints; + public List getItems() { + return items; } - public void setHints(List hints) { - this.hints = hints; + public void setItems(List items) { + this.items = items; + } + + public LockType getLockType() { + if (items.size() == 1) { + return items.get(0).lockType; + } + return null; + } + + public SQLExprTableSource getTableSource() { + if (items.size() == 1) { + return items.get(0).tableSource; + } + return null; + } + + public static class Item extends MySqlObjectImpl { + + private SQLExprTableSource tableSource = new SQLExprTableSource(); + + private LockType lockType; + + private List hints; + + @Override + public void accept0(MySqlASTVisitor visitor) { + if (visitor.visit(this)) { + acceptChild(visitor, tableSource); + } + visitor.endVisit(this); + } + + public SQLExprTableSource getTableSource() { + return tableSource; + } + + public void setTableSource(SQLExprTableSource tableSource) { + if (tableSource != null) { + tableSource.setParent(this); + } + this.tableSource = tableSource; + } + + public LockType getLockType() { + return lockType; + } + + public void setLockType(LockType lockType) { + this.lockType = lockType; + } + + public List getHints() { + return hints; + } + + public void setHints(List hints) { + this.hints = hints; + } } } 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 845b28cbd5..50afefc6b2 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 @@ -806,31 +806,62 @@ public class MySqlStatementParser extends SQLStatementParser { } MySqlLockTableStatement stmt = new MySqlLockTableStatement(); - stmt.setTableSource(this.exprParser.name()); - if (lexer.identifierEquals(READ)) { - lexer.nextToken(); - if (lexer.identifierEquals(LOCAL)) { + for(;;) { + MySqlLockTableStatement.Item item = new MySqlLockTableStatement.Item(); + + SQLExprTableSource tableSource = null; + SQLName tableName = this.exprParser.name(); + + + if (lexer.token() == Token.AS) { + lexer.nextToken(); + String as = lexer.stringVal(); + tableSource = new SQLExprTableSource(tableName, as); lexer.nextToken(); - stmt.setLockType(LockType.READ_LOCAL); } else { - stmt.setLockType(LockType.READ); + tableSource = new SQLExprTableSource(tableName); } - } else if (lexer.identifierEquals(WRITE)) { - lexer.nextToken(); - stmt.setLockType(LockType.WRITE); - } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { - lexer.nextToken(); - acceptIdentifier(WRITE); - lexer.nextToken(); - stmt.setLockType(LockType.LOW_PRIORITY_WRITE); - } else { - throw new ParserException("syntax error, expect READ or WRITE, actual " + lexer.token() + ", " + lexer.info()); + item.setTableSource(tableSource); + stmt.getItems().add(item); + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + if (lexer.identifierEquals(READ)) { + lexer.nextToken(); + if (lexer.identifierEquals(LOCAL)) { + lexer.nextToken(); + item.setLockType(LockType.READ_LOCAL); + } else { + item.setLockType(LockType.READ); + } + } else if (lexer.identifierEquals(WRITE)) { + lexer.nextToken(); + item.setLockType(LockType.WRITE); + } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { + lexer.nextToken(); + acceptIdentifier(WRITE); + lexer.nextToken(); + item.setLockType(LockType.LOW_PRIORITY_WRITE); + } else { + throw new ParserException( + "syntax error, expect READ or WRITE OR AS, actual " + lexer.token() + ", " + lexer.info()); + } + + if (lexer.token() == Token.HINT) { + item.setHints(this.exprParser.parseHints()); + } + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + break; } - if (lexer.token() == Token.HINT) { - stmt.setHints(this.exprParser.parseHints()); - } statementList.add(stmt); return true; } @@ -859,25 +890,56 @@ public class MySqlStatementParser extends SQLStatementParser { List hints = this.exprParser.parseHints(); boolean tddlHints = false; + boolean accept = false; - final Token token = lexer.token(); + + boolean acceptHint = false; + switch (lexer.token()) { + case SELECT: + case WITH: + case DELETE: + case UPDATE: + case INSERT: + case SHOW: + case REPLACE: + case TRUNCATE: + case DROP: + case ALTER: + case CREATE: + case CHECK: + case SET: + acceptHint = true; + break; + case IDENTIFIER: + acceptHint = lexer.hash_lower() == FnvHash.Constants.DUMP + || lexer.hash_lower() == FnvHash.Constants.RENAME; + break; + default: + break; + } if (hints.size() == 1 && statementList.size() == 0 - && (token == Token.SELECT || token == Token.DELETE)) { + && acceptHint) { SQLCommentHint hint = hints.get(0); - String hintText = hint.getText(); - if (hintText.startsWith("+TDDL")) { + String hintText = hint.getText().toUpperCase(); + if (hintText.startsWith("+TDDL") + || hintText.startsWith("+ TDDL") + || hintText.startsWith("TDDL") + || hintText.startsWith("!TDDL")) + { tddlHints = true; + } else if(hintText.startsWith("+")) { + accept = true; } } if (tddlHints) { - SQLStatementImpl stmt; - if (token == Token.SELECT) { - stmt = (SQLSelectStatement) this.parseStatement(); - } else { - stmt = (SQLDeleteStatement) this.parseStatement(); - } + SQLStatementImpl stmt = (SQLStatementImpl)this.parseStatement(); + stmt.setHeadHints(hints); + statementList.add(stmt); + return true; + } else if (accept) { + SQLStatementImpl stmt = (SQLStatementImpl) this.parseStatement(); stmt.setHeadHints(hints); statementList.add(stmt); return true; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 340ff1b87c..3d83cc29df 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -340,6 +340,10 @@ public interface MySqlASTVisitor extends SQLASTVisitor { void endVisit(MySqlLockTableStatement x); + boolean visit(MySqlLockTableStatement.Item x); + + void endVisit(MySqlLockTableStatement.Item x); + boolean visit(MySqlUnlockTablesStatement x); void endVisit(MySqlUnlockTablesStatement x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 34ae78d4d4..8cfb832c80 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -788,6 +788,16 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements MySq } + @Override + public boolean visit(MySqlLockTableStatement.Item x) { + return true; + } + + @Override + public void endVisit(MySqlLockTableStatement.Item x) { + + } + @Override public boolean visit(MySqlUnlockTablesStatement x) { return true; 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 0a62045fba..718daac486 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 @@ -2596,7 +2596,22 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV @Override public boolean visit(MySqlLockTableStatement x) { - print0(ucase ? "LOCK TABLES " : "lock tables "); + print0(ucase ? "LOCK TABLES" : "lock tables"); + List items = x.getItems(); + if(items.size() > 0) { + print(' '); + printAndAccept(items, ", "); + } + return false; + } + + @Override + public void endVisit(MySqlLockTableStatement x) { + + } + + @Override + public boolean visit(MySqlLockTableStatement.Item x) { x.getTableSource().accept(this); if (x.getLockType() != null) { print(' '); @@ -2611,7 +2626,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV } @Override - public void endVisit(MySqlLockTableStatement x) { + public void endVisit(MySqlLockTableStatement.Item x) { } 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 4d5bfb4ffd..00c58814d1 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 @@ -886,6 +886,16 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS } + @Override + public boolean visit(MySqlLockTableStatement.Item x) { + return false; + } + + @Override + public void endVisit(MySqlLockTableStatement.Item x) { + + } + @Override public boolean visit(MySqlUnlockTablesStatement x) { return false; diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 5be48ac625..406e0ceb0b 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -582,6 +582,7 @@ public final class FnvHash { long SCHEDULE = fnv1a_64_lower("SCHEDULE"); long COMPLETION = fnv1a_64_lower("COMPLETION"); long RENAME = fnv1a_64_lower("RENAME"); + long DUMP = fnv1a_64_lower("DUMP"); long AT = fnv1a_64_lower("AT"); long LANGUAGE = fnv1a_64_lower("LANGUAGE"); long LOGFILE = fnv1a_64_lower("LOGFILE"); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java new file mode 100644 index 0000000000..351ec5c4ba --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/AdsDumpTest_0.java @@ -0,0 +1,32 @@ +package com.alibaba.druid.bvt.sql.mysql; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLDumpStatement; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.List; + +public class AdsDumpTest_0 extends TestCase { + + public void test_0() throws Exception { + String sql = "/*+dump-merge=true*/DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id,amp.buyer_add_cart_info.pre_score,amp.buyer_add_cart_info.cart_price FROM amp.buyer_add_cart_info JOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id where (((amp.buyer_add_cart_info.seller_id=1921906956)) AND ((amp.buyer_add_cart_info.auction_id=562769960283)) AND ((amp.buyer_add_cart_info.show_price>=13300))) LIMIT 144800 "; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL); + SQLDumpStatement stmt = (SQLDumpStatement)statementList.get(0); + + assertEquals(1, statementList.size()); + + assertEquals("/*+dump-merge=true*/\n" + + "DUMP DATA SELECT amp.buyer_add_cart_info.buyer_id, amp.buyer_add_cart_info.pre_score, amp.buyer_add_cart_info.cart_price\n" + + "FROM amp.buyer_add_cart_info\n" + + "\tJOIN amp.crm_user_base_info ON amp.crm_user_base_info.user_id = amp.buyer_add_cart_info.buyer_id\n" + + "WHERE amp.buyer_add_cart_info.seller_id = 1921906956\n" + + "\tAND amp.buyer_add_cart_info.auction_id = 562769960283\n" + + "\tAND amp.buyer_add_cart_info.show_price >= 13300\n" + + "LIMIT 144800", stmt.toString()); + } + + +} \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java new file mode 100644 index 0000000000..b256dbda0a --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/update/MySqlUpdateTest_17.java @@ -0,0 +1,77 @@ +/* + * 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.update; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.stat.TableStat.Column; +import com.alibaba.druid.wall.WallUtils; + +import java.util.List; + +public class MySqlUpdateTest_17 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "update security_group_ip_count set ip_count=GREATEST(ip_count-?, 0), gmt_modified=now() where group_id=? "; + + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + print(statementList); + + 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()); + + assertEquals(1, visitor.getTables().size()); + assertEquals(3, visitor.getColumns().size()); + // assertEquals(2, visitor.getConditions().size()); + + assertTrue(visitor.containsTable("security_group_ip_count")); + + assertTrue(visitor.getColumns().contains(new Column("security_group_ip_count", "ip_count"))); + + assertEquals("UPDATE security_group_ip_count\n" + + "SET ip_count = GREATEST(ip_count - ?, 0), gmt_modified = now()\n" + + "WHERE group_id = ?", // + stmt.toString()); + assertEquals("update security_group_ip_count\n" + + "set ip_count = GREATEST(ip_count - ?, 0), gmt_modified = now()\n" + + "where group_id = ?", // + stmt.toLowerCaseString()); + + + assertTrue(WallUtils.isValidateMySql(sql)); + + { + SQLUpdateStatement update = (SQLUpdateStatement) stmt; + SQLExpr where = update.getWhere(); + assertEquals("group_id = ?", where.toString()); + } + + } +} From 6572e9a20ce754f1c50218ed7f198640581c5f38 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 16 Jul 2018 14:44:56 +0800 Subject: [PATCH 08/10] bug fixed for issue #2658 --- .../alibaba/druid/sql/ast/SQLExprImpl.java | 10 +++++++- .../druid/sql/ast/expr/SQLAggregateExpr.java | 23 +++++++++++++++++++ .../postgresql/parser/PGExprParser.java | 11 +++++++++ .../druid/sql/parser/SQLExprParser.java | 9 +++++++- .../sql/visitor/SQLASTOutputVisitor.java | 7 ++++++ .../java/com/alibaba/druid/util/FnvHash.java | 1 + 6 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java index 8aefcdc237..4843db4fe1 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLExprImpl.java @@ -17,6 +17,9 @@ package com.alibaba.druid.sql.ast; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import java.util.Collections; +import java.util.List; + public abstract class SQLExprImpl extends SQLObjectImpl implements SQLExpr { public SQLExprImpl(){ @@ -27,11 +30,16 @@ public abstract class SQLExprImpl extends SQLObjectImpl implements SQLExpr { public abstract int hashCode(); - public abstract SQLExpr clone(); + public SQLExpr clone() { + throw new UnsupportedOperationException(); + } public SQLDataType computeDataType() { return null; } + public List getChildren() { + return Collections.emptyList(); + } } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java index 8fa9e7f99d..3f1ce6798e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLAggregateExpr.java @@ -35,6 +35,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe protected SQLAggregateOption option; protected final List arguments = new ArrayList(); protected SQLKeep keep; + protected SQLExpr filter; protected SQLOver over; protected SQLName overRef; protected SQLOrderBy withinGroup; @@ -186,6 +187,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe if (option != that.option) return false; if (arguments != null ? !arguments.equals(that.arguments) : that.arguments != null) return false; if (keep != null ? !keep.equals(that.keep) : that.keep != null) return false; + if (filter != null ? !filter.equals(that.filter) : that.filter != null) return false; if (over != null ? !over.equals(that.over) : that.over != null) return false; if (overRef != null ? !overRef.equals(that.overRef) : that.overRef != null) return false; if (withinGroup != null ? !withinGroup.equals(that.withinGroup) : that.withinGroup != null) return false; @@ -199,6 +201,7 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe result = 31 * result + (option != null ? option.hashCode() : 0); result = 31 * result + (arguments != null ? arguments.hashCode() : 0); result = 31 * result + (keep != null ? keep.hashCode() : 0); + result = 31 * result + (filter != null ? filter.hashCode() : 0); result = 31 * result + (over != null ? over.hashCode() : 0); result = 31 * result + (overRef != null ? overRef.hashCode() : 0); result = 31 * result + (withinGroup != null ? withinGroup.hashCode() : 0); @@ -219,6 +222,10 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe x.setKeep(keep.clone()); } + if (filter != null) { + x.setFilter(filter.clone()); + } + if (over != null) { x.setOver(over.clone()); } @@ -236,6 +243,17 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe return x; } + public SQLExpr getFilter() { + return filter; + } + + public void setFilter(SQLExpr x) { + if (x != null) { + x.setParent(this); + } + this.filter = x; + } + public SQLDataType computeDataType() { long hash = methodNameHashCod64(); @@ -277,6 +295,11 @@ public class SQLAggregateExpr extends SQLExprImpl implements Serializable, SQLRe return true; } + if (filter == expr) { + this.filter = target; + target.setParent(this); + } + return false; } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java index 406bb9596d..1a3465cf45 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGExprParser.java @@ -334,4 +334,15 @@ public class PGExprParser extends SQLExprParser { } return alias; } + + protected void filter(SQLAggregateExpr x) { + if (lexer.identifierEquals(FnvHash.Constants.FILTER)) { + lexer.nextToken(); + accept(Token.LPAREN); + accept(Token.WHERE); + SQLExpr filter = this.expr(); + accept(Token.RPAREN); + x.setFilter(filter); + } + } } 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 942816d35b..c0f8bab92a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1445,14 +1445,21 @@ public class SQLExprParser extends SQLParser { accept(Token.RPAREN); + if (lexer.identifierEquals(FnvHash.Constants.FILTER)) { + filter(aggregateExpr); + } + if (lexer.token == Token.OVER) { over(aggregateExpr); - } return aggregateExpr; } + protected void filter(SQLAggregateExpr aggregateExpr) { + + } + protected void over(SQLAggregateExpr aggregateExpr) { lexer.nextToken(); 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 5ec6432940..ee145b1d0e 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1562,6 +1562,13 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet over.accept(this); } + final SQLExpr filter = x.getFilter(); + if (filter != null) { + print0(ucase ? "FILTER (WHERE " : "filter (where "); + printExpr(filter); + print(')'); + } + this.parameterized = parameterized; return false; } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 406e0ceb0b..1177354e88 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -652,5 +652,6 @@ public final class FnvHash { long INCREMENT = fnv1a_64_lower("INCREMENT"); long OVERWRITE = fnv1a_64_lower("OVERWRITE"); + long FILTER = fnv1a_64_lower("FILTER"); } } From b3572b7601e16efa34d10bcfcadfe3b887c3dc05 Mon Sep 17 00:00:00 2001 From: wenshao Date: Fri, 20 Jul 2018 09:47:43 +0800 Subject: [PATCH 09/10] bug fixed for mysql parser, for issue #2718 --- .../druid/sql/parser/SQLExprParser.java | 14 +++++++++++ .../select/MySqlSelectTest_196_wall.java | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java 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 c0f8bab92a..0aef79a1b4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -2270,6 +2270,8 @@ public class SQLExprParser extends SQLParser { } expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType); + } else { + return expr; } break; case TILDE: @@ -2281,6 +2283,8 @@ public class SQLExprParser extends SQLParser { rightExp = relationalRest(rightExp); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match, rightExp, getDbType()); + } else { + return expr; } break; case TILDE_STAR: @@ -2288,6 +2292,8 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Match_Insensitive, rightExp, getDbType()); + } else { + return expr; } break; case BANG_TILDE: @@ -2295,6 +2301,8 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match, rightExp, getDbType()); + } else { + return expr; } break; case BANG_TILDE_STAR: @@ -2302,6 +2310,8 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.POSIX_Regular_Not_Match_POSIX_Regular_Match_Insensitive, rightExp, getDbType()); + } else { + return expr; } break; case TILDE_EQ: @@ -2309,6 +2319,8 @@ public class SQLExprParser extends SQLParser { lexer.nextToken(); rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SAME_AS, rightExp, getDbType()); + } else { + return expr; } break; case RLIKE: @@ -2338,6 +2350,8 @@ public class SQLExprParser extends SQLParser { rightExp = relational(); expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SIMILAR_TO, rightExp, getDbType()); + } else { + return expr; } break; default: diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java new file mode 100644 index 0000000000..ae4de33a0f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_196_wall.java @@ -0,0 +1,25 @@ +package com.alibaba.druid.bvt.sql.mysql.select; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.parser.ParserException; + +import java.util.List; + +public class MySqlSelectTest_196_wall extends MysqlTest { + + public void test_0() throws Exception { + String sql = "update task_info set priority = 1, content = 'x渓螼h\u0013[\u0014\u0006饆蜭�)漉=灔�\u000B\u0011\u0011u�\uE06A圥Z[\u0017殞c怈﹝櫃&c摍0\u007Fj璟\u0004]JWRb峌膮埜\u0014譢\"瓺\\\\塼!.D牡玕\"邥\t� 佥篼緖.W=Rw4�\u001E3\t玭YF螭�\u0004�);\u0011�I\u0017�%\u0017谦漜f*\bm梄恀拒t)/�I�\"uSP蟉�\u0006I3\\\"�\u0016敐\f\\Z殷觀n\\\"餭讖;祵Y換g\uE5B7&柋\u0017�\u0011﹗A欍媞(I=\u0010�x鐹�\u000B!蜿\u0006\u0013�lQw�(33毳圳倀!\uE324=&释烃襲�&b\uE1EF�\u0013mm孺L\u0014嚍_MS7湏痘笫滴;y鶲\b爱骤求秩G-\u001By~殿揀\uE222�\u0003鮝[�Dqo:蟎'~=裼�\u001F垴蟵\\rY�\u0013.\uE3F9R\u000E�\u0012滂燶n鑲�\u0002贛龎=\u0010ミ�\u0007/%�\u001C癳c�\u000E\\Z旊\u001B�\u000B2栣玄岜�#cc吜\uE6C5�\u001B嚮醽nx�\u001B巘肅輕4E鎊\u0018E\u0018跴欱貯i\u0007蘉渚秘\u0007c\u00129狓\u0004F\u001F\f\u0013�觠3\u000B��-XS8�\u0010�\u0019V\u001E諭餸�\u000Fk\\r|\u0014V\u0005躒_A彙?E�*�\u0015琔�\u001Ep共\u000B�\u0006Z\u001F�%楳�\u001D\u001C玾郳\"\uE26B\u0011�\u0006Jj\u0016h\u0005�\u001C�\u0002�\u0002�\u0004j貌`.�\u0001�\u0005韁\"�\u0006z佉\u0012�\u001CxQ�\u0007\u0017@呃-斵曼\\0k砛0k\u0003鬨Z\uE5E9\u007F\u0006^�\u000Es\u0005欳B�\f\\0\\0��+僜'�', attribute = 0, create_time = from_unixtime(1531714297) where id = 2726633030"; + + Exception error = null; + try { + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + } catch (ParserException ex) { + error = ex; + } + + assertNotNull(error); + } +} \ No newline at end of file From 176390c5b10466441c564f0e8344f776d9f3f6d1 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 8 Aug 2018 17:38:34 +0800 Subject: [PATCH 10/10] bug fixed for DruidDataSource createPhysical error status --- .../java/com/alibaba/druid/pool/DruidAbstractDataSource.java | 3 ++- src/main/java/com/alibaba/druid/pool/DruidDataSource.java | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index 51314d1ad1..dad199045d 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -1632,7 +1632,8 @@ public abstract class DruidAbstractDataSource extends WrapperAdapter implements validateConnection(conn); validatedNanos = System.nanoTime(); - + + setFailContinuous(false); setCreateError(null); } catch (SQLException ex) { setCreateError(ex); diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 3d15d97bfd..95eba5d89e 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -2294,7 +2294,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { physicalConnection = createPhysicalConnection(); - setFailContinuous(false); } catch (OutOfMemoryError e) { LOG.error("create connection OutOfMemoryError, out memory. ", e); @@ -2466,7 +2465,6 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { connection = createPhysicalConnection(); - setFailContinuous(false); } catch (SQLException e) { LOG.error("create connection SQLException, url: " + jdbcUrl + ", errorCode " + e.getErrorCode() + ", state " + e.getSQLState(), e);