mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved mysql parser.
This commit is contained in:
+3
-1
@@ -90,7 +90,9 @@ public class MySqlReplaceStatement extends MySqlStatementImpl {
|
||||
}
|
||||
|
||||
public void setQuery(SQLQueryExpr query) {
|
||||
query.setParent(this);
|
||||
if (query != null) {
|
||||
query.setParent(this);
|
||||
}
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
|
||||
@@ -1850,10 +1850,9 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
break;
|
||||
}
|
||||
} else if (lexer.token() == Token.LPAREN) {
|
||||
lexer.nextToken();
|
||||
SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr();
|
||||
SQLSelect select = this.createSQLSelectParser().select();
|
||||
SQLQueryExpr queryExpr = new SQLQueryExpr(select);
|
||||
stmt.setQuery(queryExpr);
|
||||
accept(Token.RPAREN);
|
||||
}
|
||||
|
||||
return stmt;
|
||||
|
||||
@@ -240,6 +240,7 @@ public class SQLParser {
|
||||
case ADVISE:
|
||||
case TYPE:
|
||||
case CLOSE:
|
||||
case OPEN:
|
||||
alias = lexer.stringVal();
|
||||
lexer.nextToken();
|
||||
return alias;
|
||||
|
||||
@@ -122,6 +122,8 @@ public class DMLReplaceParserTest extends TestCase {
|
||||
SQLStatement stmt = parser.parseStatementList().get(0);
|
||||
parser.match(Token.EOF);
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (col1)\n\tSELECT id\n\tFROM t3", output);
|
||||
Assert.assertEquals("REPLACE LOW_PRIORITY INTO t1 (col1)\n" +
|
||||
"\t(SELECT id\n" +
|
||||
"\tFROM t3)", output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MySqlReplaceTest_1 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "REPLACE INTO `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`) (SELECT now(), '20170820', case a.pt\n" +
|
||||
" when 'android' then '安卓'\n" +
|
||||
" when 'ios' then 'ios'\n" +
|
||||
" when 'yunos' then '云os'\n" +
|
||||
" end AS `pt`, a.song_id, if(b.song_name is null,'新发布歌曲',b.song_name), a.play_num_1d FROM ((SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('android') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100) UNION (SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('ios') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100) UNION (SELECT pt, song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' AND `pt` IN ('yunos') GROUP BY `pt`, `song_id` ORDER BY `play_num_1d` DESC LIMIT 0, 100)) AS `a` INNER JOIN (SELECT song_id, song_name FROM `tb_003` WHERE `song_name` IS NOT NULL) AS `b` ON `a`.`song_id` = `b`.`song_id`) UNION (SELECT now(), '20170820', '整体' AS `pt`, a.song_id, if(b.song_name is null,'新发布歌曲',b.song_name), a.play_num_1d FROM (SELECT song_id, play_num_1d FROM (SELECT song_id, sum(play_num_1d) AS `play_num_1d` FROM `tb_002` WHERE `theday` = '20170820' GROUP BY `song_id`) AS `tmp` ORDER BY `play_num_1d` DESC LIMIT 0, 100) AS `a` INNER JOIN (SELECT song_id, song_name FROM `tb_003` WHERE `song_name` IS NOT NULL) AS `b` ON `a`.`song_id` = `b`.`song_id`)";
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
assertEquals("REPLACE INTO `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`)\n" +
|
||||
"\t(SELECT now(), '20170820'\n" +
|
||||
"\t\t, CASE a.pt\n" +
|
||||
"\t\t\tWHEN 'android' THEN '安卓'\n" +
|
||||
"\t\t\tWHEN 'ios' THEN 'ios'\n" +
|
||||
"\t\t\tWHEN 'yunos' THEN '云os'\n" +
|
||||
"\t\tEND AS `pt`, a.song_id\n" +
|
||||
"\t\t, if(b.song_name IS NULL, '新发布歌曲', b.song_name)\n" +
|
||||
"\t\t, a.play_num_1d\n" +
|
||||
"\tFROM (\n" +
|
||||
"\t\t(SELECT pt, song_id, SUM(play_num_1d) AS `play_num_1d`\n" +
|
||||
"\t\tFROM `tb_002`\n" +
|
||||
"\t\tWHERE `theday` = '20170820'\n" +
|
||||
"\t\t\tAND `pt` IN ('android')\n" +
|
||||
"\t\tGROUP BY `pt`, `song_id`\n" +
|
||||
"\t\tORDER BY `play_num_1d` DESC\n" +
|
||||
"\t\tLIMIT 0, 100)\n" +
|
||||
"\t\tUNION\n" +
|
||||
"\t\t(SELECT pt, song_id, SUM(play_num_1d) AS `play_num_1d`\n" +
|
||||
"\t\tFROM `tb_002`\n" +
|
||||
"\t\tWHERE `theday` = '20170820'\n" +
|
||||
"\t\t\tAND `pt` IN ('ios')\n" +
|
||||
"\t\tGROUP BY `pt`, `song_id`\n" +
|
||||
"\t\tORDER BY `play_num_1d` DESC\n" +
|
||||
"\t\tLIMIT 0, 100)\n" +
|
||||
"\t\tUNION\n" +
|
||||
"\t\t(SELECT pt, song_id, SUM(play_num_1d) AS `play_num_1d`\n" +
|
||||
"\t\tFROM `tb_002`\n" +
|
||||
"\t\tWHERE `theday` = '20170820'\n" +
|
||||
"\t\t\tAND `pt` IN ('yunos')\n" +
|
||||
"\t\tGROUP BY `pt`, `song_id`\n" +
|
||||
"\t\tORDER BY `play_num_1d` DESC\n" +
|
||||
"\t\tLIMIT 0, 100)\n" +
|
||||
"\t) `a`\n" +
|
||||
"\t\tINNER JOIN (\n" +
|
||||
"\t\t\tSELECT song_id, song_name\n" +
|
||||
"\t\t\tFROM `tb_003`\n" +
|
||||
"\t\t\tWHERE `song_name` IS NOT NULL\n" +
|
||||
"\t\t) `b`\n" +
|
||||
"\t\tON `a`.`song_id` = `b`.`song_id`)\n" +
|
||||
"\tUNION\n" +
|
||||
"\t(SELECT now(), '20170820', '整体' AS `pt`, a.song_id\n" +
|
||||
"\t\t, if(b.song_name IS NULL, '新发布歌曲', b.song_name)\n" +
|
||||
"\t\t, a.play_num_1d\n" +
|
||||
"\tFROM (\n" +
|
||||
"\t\tSELECT song_id, play_num_1d\n" +
|
||||
"\t\tFROM (\n" +
|
||||
"\t\t\tSELECT song_id, SUM(play_num_1d) AS `play_num_1d`\n" +
|
||||
"\t\t\tFROM `tb_002`\n" +
|
||||
"\t\t\tWHERE `theday` = '20170820'\n" +
|
||||
"\t\t\tGROUP BY `song_id`\n" +
|
||||
"\t\t) `tmp`\n" +
|
||||
"\t\tORDER BY `play_num_1d` DESC\n" +
|
||||
"\t\tLIMIT 0, 100\n" +
|
||||
"\t) `a`\n" +
|
||||
"\t\tINNER JOIN (\n" +
|
||||
"\t\t\tSELECT song_id, song_name\n" +
|
||||
"\t\t\tFROM `tb_003`\n" +
|
||||
"\t\t\tWHERE `song_name` IS NOT NULL\n" +
|
||||
"\t\t) `b`\n" +
|
||||
"\t\tON `a`.`song_id` = `b`.`song_id`)", SQLUtils.toMySqlString(stmt));
|
||||
assertEquals("replace into `tb_001` (`gmt_create`, `theday`, `pt`, `song_id`, `song_name`, `play_num_1d`)\n" +
|
||||
"\t(select now(), '20170820'\n" +
|
||||
"\t\t, case a.pt\n" +
|
||||
"\t\t\twhen 'android' then '安卓'\n" +
|
||||
"\t\t\twhen 'ios' then 'ios'\n" +
|
||||
"\t\t\twhen 'yunos' then '云os'\n" +
|
||||
"\t\tend as `pt`, a.song_id\n" +
|
||||
"\t\t, if(b.song_name is null, '新发布歌曲', b.song_name)\n" +
|
||||
"\t\t, a.play_num_1d\n" +
|
||||
"\tfrom (\n" +
|
||||
"\t\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\n" +
|
||||
"\t\tfrom `tb_002`\n" +
|
||||
"\t\twhere `theday` = '20170820'\n" +
|
||||
"\t\t\tand `pt` in ('android')\n" +
|
||||
"\t\tgroup by `pt`, `song_id`\n" +
|
||||
"\t\torder by `play_num_1d` desc\n" +
|
||||
"\t\tlimit 0, 100)\n" +
|
||||
"\t\tunion\n" +
|
||||
"\t\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\n" +
|
||||
"\t\tfrom `tb_002`\n" +
|
||||
"\t\twhere `theday` = '20170820'\n" +
|
||||
"\t\t\tand `pt` in ('ios')\n" +
|
||||
"\t\tgroup by `pt`, `song_id`\n" +
|
||||
"\t\torder by `play_num_1d` desc\n" +
|
||||
"\t\tlimit 0, 100)\n" +
|
||||
"\t\tunion\n" +
|
||||
"\t\t(select pt, song_id, sum(play_num_1d) as `play_num_1d`\n" +
|
||||
"\t\tfrom `tb_002`\n" +
|
||||
"\t\twhere `theday` = '20170820'\n" +
|
||||
"\t\t\tand `pt` in ('yunos')\n" +
|
||||
"\t\tgroup by `pt`, `song_id`\n" +
|
||||
"\t\torder by `play_num_1d` desc\n" +
|
||||
"\t\tlimit 0, 100)\n" +
|
||||
"\t) `a`\n" +
|
||||
"\t\tinner join (\n" +
|
||||
"\t\t\tselect song_id, song_name\n" +
|
||||
"\t\t\tfrom `tb_003`\n" +
|
||||
"\t\t\twhere `song_name` is not null\n" +
|
||||
"\t\t) `b`\n" +
|
||||
"\t\ton `a`.`song_id` = `b`.`song_id`)\n" +
|
||||
"\tunion\n" +
|
||||
"\t(select now(), '20170820', '整体' as `pt`, a.song_id\n" +
|
||||
"\t\t, if(b.song_name is null, '新发布歌曲', b.song_name)\n" +
|
||||
"\t\t, a.play_num_1d\n" +
|
||||
"\tfrom (\n" +
|
||||
"\t\tselect song_id, play_num_1d\n" +
|
||||
"\t\tfrom (\n" +
|
||||
"\t\t\tselect song_id, sum(play_num_1d) as `play_num_1d`\n" +
|
||||
"\t\t\tfrom `tb_002`\n" +
|
||||
"\t\t\twhere `theday` = '20170820'\n" +
|
||||
"\t\t\tgroup by `song_id`\n" +
|
||||
"\t\t) `tmp`\n" +
|
||||
"\t\torder by `play_num_1d` desc\n" +
|
||||
"\t\tlimit 0, 100\n" +
|
||||
"\t) `a`\n" +
|
||||
"\t\tinner join (\n" +
|
||||
"\t\t\tselect song_id, song_name\n" +
|
||||
"\t\t\tfrom `tb_003`\n" +
|
||||
"\t\t\twhere `song_name` is not null\n" +
|
||||
"\t\t) `b`\n" +
|
||||
"\t\ton `a`.`song_id` = `b`.`song_id`)", SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION));
|
||||
|
||||
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(3, visitor.getTables().size());
|
||||
assertEquals(16, visitor.getColumns().size());
|
||||
assertEquals(8, visitor.getConditions().size());
|
||||
|
||||
assertTrue(visitor.containsTable("tb_001"));
|
||||
|
||||
// assertTrue(visitor.containsColumn("t1", "id"));
|
||||
// assertTrue(visitor.containsColumn("t1", "name"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.select;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class MySqlSelectTest_51_open extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "select id as id, gmt_create as gmtCreate, gmt_modified as gmtModified, name as name, owner as owner, type as type, statement as statement, datasource as datasource, meta as meta, param_file as paramFile, sharable as sharable, data_type as dataType, status as status, config as config, project_id as projectId, plugins as plugins, field_compare as fieldCompare, field_ext as fieldExt, open as open from tb_001 where id = 12569434";
|
||||
|
||||
|
||||
List<SQLStatement> statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true);
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
|
||||
assertEquals(1, statementList.size());
|
||||
|
||||
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL);
|
||||
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(1, visitor.getColumns().size());
|
||||
// assertEquals(0, visitor.getConditions().size());
|
||||
// assertEquals(0, visitor.getOrderByColumns().size());
|
||||
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
assertEquals("SELECT id AS id, gmt_create AS gmtCreate, gmt_modified AS gmtModified, name AS name, owner AS owner\n" +
|
||||
"\t, type AS type, statement AS statement, datasource AS datasource, meta AS meta, param_file AS paramFile\n" +
|
||||
"\t, sharable AS sharable, data_type AS dataType, status AS status, config AS config, project_id AS projectId\n" +
|
||||
"\t, plugins AS plugins, field_compare AS fieldCompare, field_ext AS fieldExt, open AS open\n" +
|
||||
"FROM tb_001\n" +
|
||||
"WHERE id = 12569434", //
|
||||
output);
|
||||
}
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);
|
||||
assertEquals("select id as id, gmt_create as gmtCreate, gmt_modified as gmtModified, name as name, owner as owner\n" +
|
||||
"\t, type as type, statement as statement, datasource as datasource, meta as meta, param_file as paramFile\n" +
|
||||
"\t, sharable as sharable, data_type as dataType, status as status, config as config, project_id as projectId\n" +
|
||||
"\t, plugins as plugins, field_compare as fieldCompare, field_ext as fieldExt, open as open\n" +
|
||||
"from tb_001\n" +
|
||||
"where id = 12569434", //
|
||||
output);
|
||||
}
|
||||
|
||||
{
|
||||
String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true));
|
||||
assertEquals("SELECT id AS id, gmt_create AS gmtCreate, gmt_modified AS gmtModified, name AS name, owner AS owner\n" +
|
||||
"\t, type AS type, statement AS statement, datasource AS datasource, meta AS meta, param_file AS paramFile\n" +
|
||||
"\t, sharable AS sharable, data_type AS dataType, status AS status, config AS config, project_id AS projectId\n" +
|
||||
"\t, plugins AS plugins, field_compare AS fieldCompare, field_ext AS fieldExt, open AS open\n" +
|
||||
"FROM tb\n" +
|
||||
"WHERE id = ?", //
|
||||
output);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user