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